BZOJ 3155: Preprefix sum

大意:给一个数组,先求出SUM[I],然后动态的求出1-I的SUM[I]的和,

       这题得化公式:

      树状数组维护两个和:SUM(A[I])(1<=I<=X);

                                  SUM(A[I]*(N-I+1)) (1<=I<=X);

                                 答案就是:SUM(A[I]*(N-I+1))-SUM[A[I]]*(N-X) (1<=I<=X);

                           

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=110001;
ll s[N],t[N];
int a[N];
int n;

int lowbit(int x)
{
    return x&(-x);
}
void update1(int x,ll v)
{
    while (x<=n)
    {
        s[x]+=v;
        x+=lowbit(x);
    }
}

void update2(int x,ll v)
{
    while (x<=n)
    {
        t[x]+=v;
        x+=lowbit(x);
    }
}

ll sum1(int x)
{
    ll ans=0;
    while (x)
    {
        ans+=s[x];
        x-=lowbit(x);
    }
    return ans;
}
ll sum2(int x)
{
    ll ans=0;
    while (x)
    {
        ans+=t[x];
        x-=lowbit(x);
    }
    return ans;
}


int main()
{
    int m;
    char s[8];
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        update1(i,a[i]);
        update2(i,(ll)a[i]*(n-i+1));
    }

    while (m--)
    {
        int x,y;
        scanf("%s%d",s,&x);
        if (s[0]=='Q')
        {
            printf("%lld\n",sum2(x)-sum1(x)*(n-x));
        }
        else
        {
            scanf("%d",&y);
            update1(x,y-a[x]);
            update2(x,(ll)(y-a[x])*(n-x+1));
            a[x]=y;
        }
    }
    return 0;
}

 

 

posted on 2014-06-26 13:52  forgot93  阅读(335)  评论(0编辑  收藏  举报

导航