挺显然的一题?单点修改,前缀和数组前缀查询
树状数组就可以维护了
考虑每个位置对应询问的贡献,设询问的位置为 $x$,对于原数组 $a[i]$ 的某个位置 $i$,它会贡献 $(x-i+1)*a[i]$
即 $x*a[i]-(i-1)*a[i]$,直接对两个部分搞两个树状数组分别维护即可
具体就是搞个 $BIT_1$ 维护 $a[i]$ ,$BIT_2$ 维护 $a[i]*(i-1)$ ,对于询问 $x$
答案就是 $BIT_1.query(x)*x - BIT_2.query(x)$
注意一下 $long long$
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> using namespace std; typedef long long ll; inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); } return x*f; } const int N=2e5+7; int n,m; struct BIT { ll t[N]; inline void add(int x,ll v) { while(x<=n) t[x]+=v,x+=x&-x; } inline ll ask(int x) { ll res=0; while(x) res+=t[x],x-=x&-x; return res; } }T1,T2; int a[N]; int main() { n=read(),m=read(); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) T1.add(i,a[i]),T2.add(i,1ll*a[i]*(i-1)); char s[7]; int x,y; for(int i=1;i<=m;i++) { scanf("%s",s); x=read(); if(s[0]=='Q') { printf("%lld ",T1.ask(x)*x-T2.ask(x)); continue; } y=read(); T1.add(x,y-a[x]); T2.add(x,1ll*(y-a[x])*(x-1)); a[x]=y; } return 0; }