题目链接:
https://www.codechef.com/problems/FNCS
Solution
大力分块..
对序列分块,维护块内前缀和、块的前缀和,修改时暴力维护两个前缀和,询问单点答案就可以$O(1)$得到。
再对函数分块,维护每块函数的答案、每个位置对每块函数的贡献次数,贡献次数并不会发生改变,修改时只需要暴力修改$sqrt N$块函数答案。
要开unsigned long long!!!
Code
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; 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*10+ch-'0'; ch=getchar();} return x*f; } #define MAXN 100010 #define LL unsigned long long int N,M,val[MAXN],pl[MAXN],pr[MAXN]; struct Block{ int l,r,num[MAXN]; LL ans,sum[510]; }b[510]; int belong[MAXN],rk[MAXN],Bn,Bs; LL Sum[MAXN]; inline void Getsum(int x) { LL t=0; for (int i=b[x].l; i<=b[x].r; i++) { t+=val[i]; b[x].sum[rk[i]]=t; } b[x].sum[Bs]=t; for (int i=x; i<=Bn; i++) Sum[i]=Sum[i-1]+b[i].sum[Bs]; } inline LL Query(int x,int y) { int bx=belong[x],by=belong[y]; if (bx==by) return b[bx].sum[rk[y]]-b[bx].sum[rk[x]-1]; else if (bx+1==by) return b[by].sum[rk[y]]-b[bx].sum[rk[x]-1]+b[bx].sum[Bs]; else return b[by].sum[rk[y]]+Sum[by-1]-Sum[bx-1]-b[bx].sum[rk[x]-1]; } inline void Getnum(int x) { for (int i=b[x].l; i<=b[x].r; i++) { b[x].num[pl[i]]++; b[x].num[pr[i]+1]--; b[x].ans+=Query(pl[i],pr[i]); } for (int i=1; i<=N; i++) b[x].num[i]+=b[x].num[i-1]; } int main() { N=read(); for (int i=1; i<=N; i++) val[i]=read(); for (int i=1; i<=N; i++) pl[i]=read(),pr[i]=read(); Bs=int(sqrt(N)); for (int i=1; i<=N; i++) { if ((i-1)%Bs==0) Bn++,b[Bn].l=i; belong[i]=Bn; rk[i]=(i-1)%Bs+1; if ((i-1)%Bs==Bs-1 || i==N) b[Bn].r=i; } for (int i=1; i<=Bn; i++) Getsum(i); for (int i=1; i<=Bn; i++) Getnum(i); M=read(); while (M--) { int opt=read(),x=read(),y=read(),z; if (opt==1) { z=y-val[x]; val[x]=y; Getsum(belong[x]); for (int i=1; i<=Bn; i++) b[i].ans+=(LL)b[i].num[x]*z; } else { int bx=belong[x],by=belong[y]; LL ans=0; if (bx==by || bx+1==by) for (int i=x; i<=y; i++) ans+=Query(pl[i],pr[i]); else { for (int i=bx+1; i<=by-1; i++) ans+=b[i].ans; for (int i=x; i<b[bx+1].l; i++) ans+=Query(pl[i],pr[i]); for (int i=b[by-1].r+1; i<=y; i++) ans+=Query(pl[i],pr[i]); } printf("%llu ",ans); } } return 0; }