[BZOJ 3155] Preprefix sum
Link:
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:
观察到数据中系数的递减,从而将每项构造为两个前缀和的差