http://poj.org/problem?id=3468
线段树模板题, 不多说…
板子贴上
ac代码
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <ctime>
using namespace std;
const unsigned int MAX = 1e5+10;
unsigned int n, q, ITOR, sl, sr;
long long sn;
char c;
struct RMQ{
unsigned int l, r;
unsigned int nxl, nxr;
long long lazy;
long long sum;
} tree[(MAX<<1)];
long long Built(RMQ* point) {
point->lazy = 0;
if ((point->r-point->l) == 1) {
point->nxl = 0, point->nxr = 0;
scanf("%lld", &(point->sum));
return point->sum;
}
unsigned int n = 1;
while (n < (point->r-point->l)) n <<= 1;
point->nxl = ++ITOR;
point->nxr = ++ITOR;
tree[point->nxl].l = point->l, tree[point->nxl].r = point->l + (n>>1);
tree[point->nxr].l = point->l + (n>>1), tree[point->nxr].r = point->r;
point->sum = (Built(&tree[point->nxl]) + Built(&tree[point->nxr]));
return point->sum;
}
void init(){
ITOR = 1;
memset(&tree[0], 0, sizeof(tree[0]));
tree[1].l = 0, tree[1].r = n;
tree[1].lazy = 0;
Built(&tree[1]);
}
long long search(RMQ* now, unsigned int l, unsigned int r) {
if(now->l == now->r)
return 0;
if (l == now->l && r == now->r)
return (now->sum + (long long)now->lazy * (r-l));
now->sum += ((long long) now->lazy * (now->r-now->l));
tree[now->nxl].lazy += now->lazy, tree[now->nxr].lazy += now->lazy;
now->lazy = 0;
if (l >= tree[now->nxl].r)
return search(&tree[now->nxr], l, r);
if (r <= tree[now->nxr].l)
return search(&tree[now->nxl], l, r);
return (search(&tree[now->nxl], l, tree[now->nxl].r) +
search(&tree[now->nxr], tree[now->nxr].l, r));
}
long long add(RMQ* now, unsigned int l, unsigned int r, long long lazy) {
if (now->l == now->r) return 0;
if (l == now->l && r == now->r) {
now->lazy += lazy;
return (now->sum + now->lazy * (r-l));
}
now->sum += (long long)now->lazy * (now->r - now->l);
now->sum += lazy * (r-l);
tree[now->nxl].lazy += now->lazy, tree[now->nxr].lazy += now->lazy;
now->lazy = 0;
if (r <= tree[now->nxr].l)
return add(&tree[now->nxl], l, r, lazy);
if (l >= tree[now->nxr].l)
return add(&tree[now->nxr], l, r, lazy);
return (add(&tree[now->nxl], l, tree[now->nxl].r, lazy) +
add(&tree[now->nxr], tree[now->nxr].l, r, lazy));
}
void judge(){
init();
for (int i = 0; i < q; ++i) {
c = 0;
while (c != 'Q' && c != 'C')
c = getchar();
if (c == 'Q') {
scanf("%u%u", &sl, &sr);
printf("%lld\n", search(&tree[1], sl-1, sr));
}
if (c == 'C') {
scanf("%u%u%lld", &sl, &sr, &sn);
add(&tree[1], sl-1, sr, sn);
}
}
}
int main() {
freopen("in.in", "r", stdin);
freopen("out.out", "w", stdout);
while (scanf("%u%u", &n, &q) == 2) {
judge();
}
cerr << "teme: " << (long long)clock()*1000/CLOCKS_PER_SEC << " ms " << endl;
return 0;
}
/*************************************************************************************
void debug_bfs() {
queue<RMQ> que;
que.push(tree[1]);
while (que.size()) {
RMQ now = que.front();
que.pop();
if (now.nxl)
que.push(tree[now.nxl]);
if (now.nxr)
que.push(tree[now.nxr]);
cout << "now.l = " << now.l << ", now.r = " << now.r << endl;
cout << "now.nxl = " << now.nxl << ", nxr = " << now.nxr << endl;
cout << "now.sum = " << now.sum << ", now.lazy = " << now.lazy << endl;
cout << endl;
}
}
****************************************************************************************
void debug() {
for (int i = 0; i <= ITOR; ++i) {
cout << "ITOR = " << i << endl;
RMQ now = tree[i];
cout << "\tnow.l = " << tree[i].l << ", now.r = " << tree[i].r << endl;
cout << "\tnow.nxl = " << tree[i].nxl << ", nxr = " << tree[i].nxr << endl;
cout << "\tnow.sum = " << tree[i].sum << ", now.lazy = " << tree[i].lazy << endl;
cout << endl;
}
}
*************************************************************************************/
目测是写挫了, 大概还能优化出 2 到 3 倍的常数, 开始没想到 iostream 和 stdio 会差出四倍来, 一度卡到10倍常数…..
ps. 然而要来同学1700ms的代码本地对拍发现还是我的块233333, 可能是poj老掉牙的优化的问题吧.
随机数生成
#include <stdio.h>
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int n, q;
int main() {
freopen("in.in", "w", stdout);
srand(time(NULL));
for (int i = 0; i < 100000; ++i) {
n = 0, q = 0;
while (n < 1) n = rand() % 300;
while (!q) q = rand() % 200;
printf("%d %d\n", n, q);
for (int i = 0; i < n; ++i)
cout << (int)(rand() % 30000) * ((rand()%2) ? 1 : -1) << " ";
cout << endl;
for (int i = 0; i < q-1; ++i) {
int l = 0, r = 0;
while (!l) l = rand() % (n+1) ;
while (r < l) r = rand() % (n+1);
if (rand()% 3)
printf("C %d %d %d\n", l, r, (rand() % 30000) * ((rand()%2) ? 1 : -1));
else
printf("Q %d %d\n", l, r);
}
printf("Q 1 1\n");
}
return 0;
}
2017-08-30