BZOJ3155: Preprefix sum

【传送门:BZOJ3155


简要题意:

  给出一个序列a[i],s[i]表示a[1]到a[i]的和,ss[i]表示s[1]到s[i]的和,对于这个序列有两种操作:

  1.Query x,输出ss[x]

  2.Modify x d,将a[x]改为d


题解:

  本来想用树状数组,结果写炸了

  还是老老实实写线段树

  将s数组作为叶子节点的值存进线段树,对于第一种操作只需要输出1到x的和就可以了,而第二种操作因为是区间修改,所以用lazy标记来进行继承,对于每次修改,将tr[x].c+=(tr[x].r-tr[x].l+1)*c,这样就能维护值了


参考代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
struct node
{
    int l,r,lc,rc;LL c;
    LL lazy;
}tr[210000];int trlen;
LL a[110000],s[110000];
void bt(int l,int r)
{
    trlen++;int now=trlen;
    tr[now].l=l;tr[now].r=r;
    tr[now].lc=tr[now].rc=-1;
    tr[now].lazy=0;
    if(l==r) tr[now].c=s[l];
    else
    {
        int mid=(l+r)/2;
        tr[now].lc=trlen+1;bt(l,mid);
        tr[now].rc=trlen+1;bt(mid+1,r);
        tr[now].c=tr[tr[now].lc].c+tr[tr[now].rc].c;
    }
}
void update(int x)
{
    int lc=tr[x].lc,rc=tr[x].rc;
    if(lc!=-1)
    {
        tr[lc].c+=LL(tr[lc].r-tr[lc].l+1)*tr[x].lazy;
        tr[lc].lazy+=tr[x].lazy;
    }
    if(rc!=-1)
    {
        tr[rc].c+=LL(tr[rc].r-tr[rc].l+1)*tr[x].lazy;
        tr[rc].lazy+=tr[x].lazy;
    }
    tr[x].lazy=0;
}
LL getsum(int now,int l,int r)
{
    if(tr[now].l==l&&tr[now].r==r) return tr[now].c;
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
    if(tr[now].lazy!=0) update(now);
    if(r<=mid) return getsum(lc,l,r);
    else if(l>mid) return getsum(rc,l,r);
    else return getsum(lc,l,mid)+getsum(rc,mid+1,r);
    tr[now].c=tr[lc].c+tr[rc].c;
}
void change(int now,int l,int r,LL c)
{
    if(tr[now].l==l&&tr[now].r==r)
    {
        tr[now].lazy+=c;
        tr[now].c+=LL(r-l+1)*c;
        return ;
    }
    int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
    if(tr[now].lazy!=0) update(now);
    if(r<=mid) change(lc,l,r,c);
    else if(l>mid) change(rc,l,r,c);
    else
    {
        change(lc,l,mid,c);
        change(rc,mid+1,r,c);
    }
    tr[now].c=tr[lc].c+tr[rc].c;
}
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    s[0]=0;
    for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];
    trlen=0;bt(1,n);
    char st[11];
    for(int i=1;i<=m;i++)
    {
        int x;
        scanf("%s%d",st+1,&x);
        if(st[1]=='Q') printf("%lld\n",getsum(1,1,x));
        else
        {
            LL d;
            scanf("%lld",&d);
            change(1,x,n,d-a[x]);
            a[x]=d;
        }
    }
    return 0;
}

 

posted @ 2018-03-03 11:15  Star_Feel  阅读(155)  评论(0编辑  收藏  举报