POJ 3468_A Simple Problem with Integers(线段树)

来源:互联网 发布:js字符串实例 编辑:程序博客网 时间:2024/06/05 06:41

题意:

给定序列及操作,求区间和。

分析:

线段树,每个节点维护两个数据:

  • 该区间每个元素所加的值
  • 该区间元素和

可以分为“路过”该区间和“完全覆盖”该区间考虑。

代码:

#include<cstdio>#include<iostream>#include<cmath>using namespace std;typedef long long ll;//[l,r)const int maxn = 300005;ll sum[maxn], add[maxn];int v[maxn];void update(int a, int b, int x, int k, int l, int r){    if(a <= l && r <= b) add[k] += x;    else if(l < b && a < r){        sum[k] += (min(r,b) - max(l,a))*x;        update(a, b, x, k * 2 + 1, l, (l+r)/2);        update(a, b,x, k * 2 + 2, (l+r)/2, r);    }}ll query(int a, int b, int k, int l, int r){    if(a >= r|| b <= l) return 0;    else if(a <= l&&r <= b) return (r - l) * add[k] + sum[k];    else {        ll res = (min(b,r)-max(a,l)) * add[k];        res += query(a, b, k * 2 + 1, l, (l+r)/2);        res += query(a, b, k * 2 + 2, (l + r)/2, r);        return res;    }}int main (void){    int n, q;scanf("%d%d",&n,&q);    int a, b, c;    for(int i = 0; i < n; i++){        scanf("%d",&v[i]);        update(i, i + 1, v[i], 0, 0, n);    }    for(int i = 0; i < q; i++){        getchar();        if(getchar()=='C'){            scanf("%d%d%d", &a, &b, &c);            update(a-1, b, c, 0 , 0, n);        }else{            scanf("%d%d",&a, &b);            printf("%I64d\n",query(a - 1, b, 0, 0, n));        }    }    return 0;}

写的时候还是磕磕绊绊,看来当初学的时候理解的并不好

0 0
原创粉丝点击