1. 程式人生 > >解題:洛谷3396 雜湊衝突

解題:洛谷3396 雜湊衝突

題面

題外話:現在還不知道退不退役啊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 }
View Code