P3396 哈希冲突

P3396 哈希冲突

题目描述

众所周知,模数的hash会产生冲突。例如,如果模的数p=7,那么411便冲突了。

B君对hash冲突很感兴趣。他会给出一个正整数序列value[]

自然,B君会把这些数据存进hash池。第value[k]会被存进(k%p)这个池。这样就能造成很多冲突。

B君会给定许多个px,询问在模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,所以少于\sqrt{n}n个数对答案有贡献。所以对于 p>\sqrt{n}p>n,暴力统计的复杂度是 O(\sqrt{n})O(n)..

接着考虑修改。显然我们把p<size的值全都更新一遍就行。复杂度也是 O(\sqrt{n})O(n).

这样,我们就在O((m+n)*sqrt(n) )O((m+n)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;
}

  

 

posted @ 2019-03-14 17:13  孑行  阅读(202)  评论(0编辑  收藏  举报