题意:
单点修改$a$
询问$a$的区间和$f$的区间和
原来普通计算机是这道题改编的吧...
对$f$分块,预处理$c[i][j]$为块i中$a_j$出现几次,$O(NH(N))$,只要每个块差分加上然后扫一遍就行了不用树状数组之类的
修改,整块直接改,还要单点修改$a$
查询,整块直接查,两边暴力查询$a$的区间和
对$a$的操作可以用树状数组,也可以再分块维护前缀和实现$O(N)-O(1)$
这样不用带一个log总复杂度$O(NH(N))$
实测快了0.4s
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; const int N=1e5+5,M=350; typedef unsigned long long ll; inline int read(){char c=getchar();int x=0,f=1;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x*f; } int n,Q,op,x,y; ll a[N],s[N]; int pos[N],m,block; struct _Block{int l,r;} b[M], f[N]; inline void iniBlock(){block=sqrt(n); m=(n-1)/block+1;for(int i=1;i<=n;i++) pos[i]=(i-1)/block+1;for(int i=1;i<=m;i++) b[i].l=(i-1)*block+1,b[i].r=i*block;b[m].r=n; } struct BlockA{ll add[M];void Add(int x,ll v){for(int i=x;i<=b[pos[x]].r;i++) s[i]+=v;for(int i=pos[x]+1;i<=m;i++) add[i]+=v;}ll fun(_Block &x){return s[x.r]+add[ pos[x.r] ] - (s[x.l-1]+add[ pos[x.l-1] ]);} }A; struct Block{int c[M][N],s[N];ll sum[N];void ini(){for(int i=1;i<=m;i++){for(int j=b[i].l ; j<=b[i].r ; j++)s[ f[j].l ]++,s[ f[j].r+1 ]--;int *cc=c[i];for(int j=1;j<=n;j++) cc[j]=cc[j-1]+s[j],sum[i]+=cc[j]*a[j],s[j]=0;}}void cha(int x,ll v){ll t=v-a[x]; A.Add(x,t);for(int i=1;i<=m;i++) sum[i]+=c[i][x]*t;a[x]=v;}ll que(int l,int r){ll re=0;if(pos[l]==pos[r])for(int i=l;i<=r;i++) re+=A.fun(f[i]);else{for(int i=pos[l]+1;i<=pos[r]-1;i++) re+=sum[i];for(int i=l;i<=b[pos[l]].r;i++) re+=A.fun(f[i]);for(int i=b[pos[r]].l;i<=r;i++) re+=A.fun(f[i]);}return re;} }B; int main(){freopen("in","r",stdin);n=read();for(int i=1;i<=n;i++) a[i]=read(),s[i]=s[i-1]+a[i];for(int i=1;i<=n;i++) f[i].l=read(),f[i].r=read();iniBlock();B.ini();Q=read();while(Q--){op=read();x=read();y=read();if(op==1) B.cha(x,y);else printf("%llu\n",B.que(x,y));} }
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define pii pair<int,int> #define MP make_pair #define fir first #define sec second const int N=1e5+5,M=350; typedef unsigned long long ll; inline int read(){char c=getchar();int x=0,f=1;while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}return x*f; } int n,Q,op,x,y; ll a[N]; pii f[N]; struct BIT{ll c[N];inline void add(int p,ll v){for(;p<=n;p+=(p&-p)) c[p]+=v;}inline ll sum(int p){ll re=0;for(;p;p-=(p&-p)) re+=c[p];return re;} }C; inline ll fun(int x){return C.sum(f[x].sec)-C.sum(f[x].fir-1);} struct _Block{int l,r;ll sum;}; struct Block{int block,m,pos[N],c[M][N],s[N];_Block b[M];void ini(){block=sqrt(n); m=(n-1)/block+1;for(int i=1;i<=n;i++) pos[i]=(i-1)/block+1;for(int i=1;i<=m;i++){b[i].l=(i-1)*block+1; b[i].r= i==m ? n : i*block;for(int j=b[i].l ; j<=b[i].r ; j++)s[ f[j].fir ]++,s[ f[j].sec+1 ]--;int *cc=c[i];for(int j=1;j<=n;j++) cc[j]=cc[j-1]+s[j],b[i].sum+=cc[j]*a[j],s[j]=0;}}void cha(int x,ll v){v-=a[x];for(int i=1;i<=m;i++) b[i].sum+=c[i][x]*v;C.add(x,v); a[x]+=v;}ll que(int l,int r){ll re=0;if(pos[l]==pos[r])for(int i=l;i<=r;i++) re+=fun(i);else{for(int i=pos[l]+1;i<=pos[r]-1;i++) re+=b[i].sum;for(int i=l;i<=b[pos[l]].r;i++) re+=fun(i);for(int i=b[pos[r]].l;i<=r;i++) re+=fun(i);}return re;} }B; int main(){freopen("in","r",stdin);n=read();for(int i=1;i<=n;i++) a[i]=read(),C.add(i,a[i]);for(int i=1;i<=n;i++) f[i].fir=read(),f[i].sec=read();B.ini();Q=read();while(Q--){op=read();x=read();y=read();if(op==1) B.cha(x,y);else printf("%llu\n",B.que(x,y));} }