实际上跟哈希没有关系,跟分块也没关系。
sum[p][k]表示取模p,余k的所有下标位置的和。up为sqrt(n)。显然我们可以在O(nsqrt(n))的时间内预处理出sum数组。对于p不超过up的询问直接输出即可。
如果出现修改操作,我们只要单独修改被修改位置对整个sum数组的影响即可。复杂度为O(sqrt(n))。
对于p超过up的询问,我们考虑,因为p>sqrt(n),所以在这个情况下,需要求和的下标个数总数不超过sqrt(n),我们暴力求即可。
很巧妙的根号做法。q<=sqrt(n)内如果暴力做,需要求和的下标个数过多,所以我们预处理。对于q>sqrt(n),我们需要球的下标个数少,不超过sqrt(n),暴力求即可。
1 #include <cstdio> 2 #include <cmath> 3 using namespace std; 4 const int MAXN = 150010; 5 int n,m,up; 6 int val[MAXN],sum[400][MAXN]; 7 int main() 8 { 9 scanf("%d%d",&n,&m); 10 for (int i = 1;i <= n;i++) 11 scanf("%d",&val[i]); 12 up = sqrt(n); 13 for (int p = 1;p <= up;p++) 14 for (int i = 1;i <= n;i++) 15 sum[p][i % p] += val[i]; 16 int tx,ty; 17 char s[10]; 18 for (int i = 1;i <= m;i++) 19 { 20 scanf("%s%d%d",s,&tx,&ty); 21 if (s[0] == 'A') 22 { 23 if (tx <= up) 24 printf("%d\n",sum[tx][ty]); 25 else 26 { 27 int res = 0; 28 for (int i = 0;i * tx + ty <= n;i++) 29 res += val[i * tx + ty]; 30 printf("%d\n",res); 31 } 32 }else 33 { 34 for (int p = 1;p <= up;p++) 35 sum[p][tx % p] -= val[tx]; 36 val[tx] = ty; 37 for (int p = 1;p <= up;p++) 38 sum[p][tx % p] += val[tx]; 39 } 40 } 41 return 0; 42 }