BZOJ3155: Preprefix sum

Posted mt-li

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3155: Preprefix sum相关的知识,希望对你有一定的参考价值。

Description

 

Input

 

第一行给出两个整数N,M。分别表示序列长度和操作个数
接下来一行有N个数,即给定的序列a1,a2,....an
接下来M行,每行对应一个操作,格式见题目描述

 

Output

对于每个询问操作,输出一行,表示所询问的SSi的值。

 

Sample Input

5 3
1 2 3 4 5
Query 5
Modify 3 2
Query 5

Sample Output

35
32

HINT

1<=N,M<=100000,且在任意时刻0<=Ai<=100000

 

题目传送门

 

本来想用树状数组维护前缀和再枚举的。。。

神tm这和暴力好像没什么不一样啊

树状数组又不能支持区间修改

等等,好像可以用容斥原理做

c[x]=1+2+3+4+...+x

cc[x]=n*1+(n-1)*2+....+x

那么答案就是cc[x]-(n-x)*c[x];

 

代码如下:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
ll a[210000];
ll c[210000],cc[210000];
ll lowbit(ll x){return x&(-x);}
int n,m;
void change(ll x,ll d)
{
    int N=(n-x+1);
    while(x<=n)
    {
        c[x]+=d;cc[x]+=N*d;
        x+=lowbit(x);
    }
}
char st[15];
ll getsum(ll x)
{
    ll sum=0,ans=0;int N=n-x;
    while(x>=1)
    {
        sum+=cc[x],ans+=c[x];
        x-=lowbit(x);
    }
    return sum-N*ans;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%lld",&a[i]),change(i,a[i]);
    while(m--)
    {
        scanf("%s",st+1);
        if(st[1]==M)
        {
            ll x,y;
            scanf("%lld%lld",&x,&y);
            change(x,y-a[x]);
            a[x]=y;
        }
        else
        {
            ll x;
            scanf("%lld",&x);
            printf("%lld\n",getsum(x));
        }
    }
    return 0;
}

by_lmy

 

以上是关于BZOJ3155: Preprefix sum的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 3155 Preprefix sum

bzoj3155: Preprefix sum

BZOJ3155: Preprefix sum

BZOJ3155: Preprefix sum

3155: Preprefix sum

差分+树状数组p4868Preprefix sum