题外话:现在还不知道退不退役啊QAQ,因为发挥太渣,把Day1T3和Day2T1这仅有的两道有区分度的题全写挂了(没区分度的其他题**倒挺稳。。。),退不退役全看数据湿度了(400-460,教练建议的线是420,orz i207M 530+)
在可能是苟在机房的最后一周里打算学学分块和莫队=。=
分块不只是一种处理序列问题的方法,更多的是一种均摊复杂度的思想(比如这个题)
(我好像在汇总里写过这个思想)
我们现在有两种暴力:第一种暴力是$O(mod)$的,即先$O(n*mod)$处理在模某数意义下每个池子里的数,然后每次$O(1)$查表+$O(mod)$修改,问题是模数很大时会GG;第二种暴力是$O(\frac{n}{mod})$,直接在序列上每隔$mod$统计,然后$O(1)$修改一下序列。然后你把这两种暴力揉在一起,对于$mod<=sqrt(n)$的情况采用暴力1,对于$mod>sqrt(n)$的情况采用暴力2,于是得到了一个$O((n+m)sqrt(n))$的算法
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=150005,Sqrt=390; 6 long long a[N],bkt[Sqrt+5][Sqrt+5]; 7 int n,m,t1,t2; char rd[5]; 8 int main () 9 { 10 scanf("%d%d",&n,&m); 11 for(int i=1;i<=n;i++) 12 { 13 scanf("%lld",&a[i]); 14 for(int j=1;j<=Sqrt;j++) 15 bkt[j][i%j]+=a[i]; 16 } 17 while(m--) 18 { 19 scanf("%s%d%d",rd,&t1,&t2); 20 if(rd[0]=='A') 21 { 22 if(t1<=Sqrt) 23 printf("%lld\n",bkt[t1][t2%t1]); 24 else 25 { 26 long long ans=0; 27 for(int i=t2;i<=n;i+=t1) 28 ans+=a[i]; 29 printf("%lld\n",ans); 30 } 31 } 32 else 33 { 34 for(int i=1;i<=Sqrt;i++) 35 bkt[i][t1%i]+=t2-a[t1]; 36 a[t1]=t2; 37 } 38 } 39 return 0; 40 }