[BZOJ 3155] Preprefix sum

Link:

BZOJ 3155 传送门

Solution:

我们发现要维护的序列的每一项都有$i$项要维护,

我们要将每一项转化为只有1项要维护才能$log(n)$维护(否则每对一个值更新要更新$n$个值)

 

于是我们将每一项拆为两个前缀和相减,

开两个树状数组,第一个维护$a[i]$前缀和,第二个维护$(n-i+1)*a[i]$的前缀和

$res=BIT2[x]-BIT1[x]*(n-x)$

Code:

#include <bits/stdc++.h>

using namespace std;

const int MAXN=1e5+10;
typedef long long ll;
char op[10];
ll bit[2][MAXN];
int dat[MAXN],n,m,x,y;

void Update(int f,int pos,ll val){while(pos<=n) bit[f][pos]+=val,pos+=pos&(-pos);}
ll Query(int f,int pos)
{
    ll ret=0;
    while(pos){ret+=bit[f][pos];pos-=pos&(-pos);}
    return ret;
} 

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&dat[i]),Update(0,i,dat[i]),Update(1,i,1ll*dat[i]*(n+1-i));
    while(m--)
    {
        scanf("%s",op);
        if(op[0]=='Q')
            scanf("%d",&x),
            printf("%lld\n",Query(1,x)-1ll*Query(0,x)*(n-x));
        else
            scanf("%d%d",&x,&y),
            Update(0,x,y-dat[x]),Update(1,x,1ll*(n-x+1)*(y-dat[x])),dat[x]=y;
    }
    return 0;
}

Review:

观察到数据中系数的递减,从而将每项构造为两个前缀和的差

posted @ 2018-06-02 21:54  NewErA  阅读(154)  评论(0编辑  收藏  举报