bzoj3155: Preprefix sum 树状数组

来源:互联网 发布:java cs架构开发书本 编辑:程序博客网 时间:2024/06/08 06:52

题意:动态修改,查询前缀和的前缀和。
一开始下意识树套树,看了看别人长度果断否决了= =,然后没什么思路。
然后我试着化简了一发。。
SSi=j=1i(nj+1)a[j](ni)sum[j]
简单,两个树状数组搞定。

#include<cstdio>#include<cstring>#include<algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=2e5+5;typedef long long ll;int n,m;ll t[N],a[N];ll t1[N],b[N];char ch[10];inline int lowbit(int x){    return x&(-x);}inline void add(int x,ll y){    while (x<=n)    {        t[x]+=y;        x+=lowbit(x);    }}inline ll ask(int x){    ll ans=0;    while (x>0)    {        ans+=t[x];        x-=lowbit(x);    }    return ans;}inline void add1(int x,ll y){    while (x<=n)    {        t1[x]+=y;        x+=lowbit(x);    }}inline ll ask1(int x){    ll ans=0;    while (x>0)    {        ans+=t1[x];        x-=lowbit(x);    }    return ans;}int main(){    scanf("%d%d",&n,&m);    fo(i,1,n)    {        scanf("%lld",&a[i]);        add(i,a[i]);        b[i]=1ll*(n-i+1)*a[i];        add1(i,b[i]);    }    fo(i,1,m)    {        scanf("%s",ch);        int x,y;        if (ch[0]=='Q')        {            scanf("%d",&x);            printf("%lld\n",ask1(x)-(n-x)*ask(x));        }        else        {            scanf("%d%d",&x,&y);            add(x,-a[x]);            a[x]=y;            add(x,a[x]);            add1(x,-b[x]);            b[x]=1ll*a[x]*(n-x+1);            add1(x,b[x]);        }     }}
原创粉丝点击