POJ3468(线段树成段增加)

来源:互联网 发布:小米手环数据修改攻略 编辑:程序博客网 时间:2024/04/20 03:40

题目链接

大牛博客链接
ac代码:

#include<iostream>#include<cstdio>#include<algorithm>using namespace std;const int maxn=100000+5;typedef long long ll;struct tree{    ll l,r,sum,inc;}a[maxn*4];ll c[maxn];void build(ll o,ll l,ll r)   //初始建树 {    a[o].l=l,a[o].r=r,a[o].inc=0;    if(l==r)    {        a[o].sum=c[l];        return;    }    else    {        ll m=(l+r)/2;        build(o*2,l,m);        build(o*2+1,m+1,r);        a[o].sum=a[o*2].sum+a[o*2+1].sum;        return;    }}void add(ll o,ll p,ll q,ll v)   //对区间[p,q] 上的每个点增加v {    if(a[o].l==p&&a[o].r==q)    {        a[o].inc+=v;        return;    }    a[o].sum+=v*(q-p+1);    ll m=(a[o].l+a[o].r)/2;    if(q<=m) add(o*2,p,q,v);    else if(p>m) add(o*2+1,p,q,v);    else    {        add(o*2,p,m,v);        add(o*2+1,m+1,q,v);    }    return;}ll query(ll o,ll p,ll q)     //查询区间[p,q]的和 {    if(a[o].l==p&&a[o].r==q)    {        return a[o].sum+(q-p+1)*a[o].inc;    }    a[o].sum+=(a[o].r-a[o].l+1)*a[o].inc;     //将标记向下推     int m=(a[o].l+a[o].r)/2;    add(o*2,a[o].l,m,a[o].inc);    add(o*2+1,m+1,a[o].r,a[o].inc);    a[o].inc=0;                             if(q<=m) return query(o*2,p,q);    else if(p>m) return query(o*2+1,p,q);    else return query(o*2,p,m)+query(o*2+1,m+1,q);}int main(){    ll n,q;    scanf("%I64d%I64d",&n,&q);    for(int i=1;i<=n;i++)        scanf("%I64d",&c[i]);    build(1,1,n);    char ch;    for(int i=1;i<=q;i++)    {        cin >> ch;        if(ch=='Q')        {            ll p,q;            scanf("%I64d%I64d",&p,&q);            printf("%I64d\n",query(1,p,q));        }        else if(ch=='C')        {            ll a,b,v;            scanf("%I64d%I64d%I64d",&a,&b,&v);            add(1,a,b,v);        }    }}
1 0
原创粉丝点击