解题:洛谷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
",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
",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
原文地址:https://www.cnblogs.com/ydnhaha/p/9954688.html