POJ-3468(线段树区间更新区间查询)

来源:互联网 发布:西科软件招聘 编辑:程序博客网 时间:2024/03/29 15:49

题目:http://poj.org/problem?id=3468

终于将线段(满二叉)树的令一种应用搞懂了,本题需要注意的是中间pushDown的过程中,对delta和len * delta的临时存储要用64bit整数(WA了2次才找到):


#include <cstdio>typedef __int64 LL;const int LEAVES = 128 * 1024;struct Segment{    int left, right;    LL  sum, delta;};Segment node[LEAVES * 2];void build(int l, int r, int i){    node[i].left = l;    node[i].right = r;    node[i].sum = 0;    node[i].delta = 0;    if(l == r) return;    int m = (l + r) >> 1;    build(l, m, i << 1);    build(m + 1, r, i << 1 | 1);}inline void pushUp(int i){    node[i].sum = node[i << 1].sum + node[i << 1 | 1].sum;}inline void pushDown(int i){    int l = i << 1, r = i << 1 | 1;    LL d = node[i].delta, lend = (node[l].right - node[l].left + 1) * d;    node[l].delta += d;    node[l].sum += lend;    node[r].delta += d;    node[r].sum += lend;    node[i].delta = 0;}void update(int p, int i, int d){    if(node[i].left == node[i].right){        node[i].sum += d;        return;    }    int m = (node[i].left + node[i].right) >> 1;    if(m >= p) update(p, i << 1, d);    else update(p, i << 1 | 1, d);    pushUp(i);}void update(int l, int r, int i, int d){    if(l <= node[i].left && r >= node[i].right){        node[i].sum += d * (node[i].right - node[i].left + 1);        node[i].delta += d;        return;    }    if(node[i].delta) pushDown(i);    int m = (node[i].left + node[i].right) >> 1;    if(m >= r) update(l, r, i << 1, d);    else if(m < l) update(l, r, i << 1 | 1, d);    else{        update(l, m, i << 1, d);        update(m + 1, r, i << 1 | 1, d);    }    pushUp(i);}LL query(int l, int r, int i){    if(l <= node[i].left && r >= node[i].right) return node[i].sum;    if(node[i].delta) pushDown(i);    int m = (node[i].left + node[i].right) >> 1;    if(m >= r) return query(l, r, i << 1);    else if(m < l) return query(l, r, i << 1 | 1);    else return query(l, m, i << 1) + query(m + 1, r, i << 1 | 1);}int ceilingPower2(int n){    int m = 1;    for(; m < n; m <<= 1) ;    return m;}int main(){    char o;    int N, Q, i, d, l, r;    while(scanf("%d%d", &N, &Q) == 2){        build(1, ceilingPower2(N), 1);        for(i = 1; i <= N; ++i){            scanf("%d", &d);            update(i, 1, d);        }        while(Q--){            scanf(" %c %d %d", &o, &l, &r);            if(o == 'Q') printf("%I64d\n", query(l, r, 1));            else{                scanf("%d", &d);                update(l, r, 1, d);            }        }    }    return 0;}

0 0