P3396 哈希冲突
P3396 哈希冲突
题目描述
众所周知,模数的hash会产生冲突。例如,如果模的数
p=7
,那么4
和11
便冲突了。B君对hash冲突很感兴趣。他会给出一个正整数序列
value[]
。自然,B君会把这些数据存进hash池。第
value[k]
会被存进(k%p)
这个池。这样就能造成很多冲突。B君会给定许多个
p
和x
,询问在模p
时,x
这个池内数的总和
。另外,B君会随时更改
value[k]
。每次更改立即生效。保证1<=p<n1<=p<n.
输入输出格式
输入格式:
第一行,两个正整数
n,m
,其中n
代表序列长度,m
代表B君的操作次数。第一行,
n
个正整数,代表初始序列。接下来
m
行,首先是一个字符cmd
,然后是两个整数x,y
。
若
cmd='A'
,则询问在模x
时,y
池内数的总和。若
cmd='C'
,则将value[x]
修改为y
。
输出格式:
对于每个询问输出一个正整数,进行回答。
- 本题的思路很巧妙:只预处理出前sqrt(n)部分的答案,询问时如果x<=sqrt(n),直接O(1)输出答案,否则暴力计算即可(因为x>sqrt(n)所以需要统计的个数也不超过sqrt(n))
如果p超过size,我们就暴力统计并回答。因为 p>\sqrt{n}p>n
代码:
#include <cstdio> #include <cctype> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> using namespace std; #define res register int //typedef long long LL; inline int read() { int x(0),f(1); char ch; while(!isdigit(ch=getchar())) if(ch=='-') f=-1; while(isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return f*x; } const int N=150000+10; int v[N],ans[500][500];//sqrt(N) = 400 // mod p = x int n,m,t; int main() { n=read(); m=read(); t=sqrt(1.0*n); for(res i=1 ; i<=n ; ++i) v[i]=read(); for(res i=1 ; i<=n ; ++i) for(res j=1 ; j<=t ; ++j) ans[j][i%j] += v[i]; for(res k=1 ; k<=m ; ++k) { char s; cin>>s; int x=read(),y=read(); if(s=='A') { if(x<=t) printf("%d\n",ans[x][y]); else { int tmp=0; for(res i=y ; i<=n ; i+=x) tmp+=v[i]; printf("%d\n",tmp); } } else if(s=='C') { for(res p=1 ; p<=t ; ++p) ans[p][x%p]+=(y-v[x]); v[x]=y; } } return 0; }