洛谷 P3396 哈希冲突

洛谷 P3396 哈希冲突

Problem

P3396 哈希冲突

Solution

本文摘自基础数据结构学习笔记

先想两种极端的做法

  • 对于每个询问,暴力计算\(k,k+p,k+2\times p\dots\)\(value\)之和。
  • 预处理出\(ans[p][k]\)表示在\(\bmod p\)的意义下,余数为\(k\)\(value\)之和。

第一种方法时间\(\rm O(n^2)\),空间\(\rm O(1)\);第二种方法时间\(\rm O(1)\),空间\(O(n^2)\)

考虑根号分治

对于\(p\le \sqrt n\),我们预处理,保存在数组\(ans[p][k]\)中。空间\(\rm O(\sqrt n\times\sqrt n)=\rm O(n)\),时间上预处理\(\rm O(n\sqrt n)\),修改\(\rm O(\sqrt n)\),查询\(\rm O(1)\).

对于\(p>\sqrt n\),我们不预处理,每一次询问暴力统计。每次统计的数量不会超过\(\dfrac np\le \sqrt n\).

\(\color{white}我做了那些Ynoi我都白做了啊啊啊,这么简单的一个根号分治我都想不出来……我太菜了……\color{gray}awa\)

Code

/**************************************************************
 * Problem: 3396
 * Author: Vanilla_chan
 * Date: 20210402
 * E-Mail: Vanilla_chan@outlook.com
**************************************************************/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<limits.h>
#define IL inline
#define re register
#define LL long long
#define ULL unsigned long long
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug
#endif
#ifdef ONLINE_JUDGE
char buf[1<<23],* p1=buf,* p2=buf,obuf[1<<23],* O=obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
using namespace std;

namespace oi
{
	inline bool isdigit(const char& ch)
	{
		return ch<='9'&&ch>='0';
	}
	inline bool isalnum(const char& ch)
	{
		return (ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9');
	}
	struct istream
	{
		char ch;
		bool fu;
		template<class T>inline istream& operator>>(T& d)
		{
			fu=(d=0);
			while(!isdigit(ch)&&ch!='-') ch=getchar();
			if(ch=='-') fu=1,ch=getchar();
			d=ch-'0';ch=getchar();
			while(isdigit(ch))
				d=(d<<3)+(d<<1)+(ch^'0'),ch=getchar();
			if(fu) d=-d;
			return *this;
		}
		inline istream& operator>>(char& ch)
		{
			ch=getchar();
			for(;!isalnum(ch);ch=getchar());
			return *this;
		}
		inline istream& operator>>(string& str)
		{
			str.clear();
			for(;!isalnum(ch);ch=getchar());
			while(isalnum(ch))
				str+=ch,ch=getchar();
			return *this;
		}
	}cin;
	inline int read()
	{
		int x=0,fu=1;
		char ch=getchar();
		while(!isdigit(ch)&&ch!='-') ch=getchar();
		if(ch=='-') fu=-1,ch=getchar();
		x=ch-'0';ch=getchar();
		while(isdigit(ch)) { x=x*10+ch-'0';ch=getchar(); }
		return x*fu;
	}
	int G[55];
	template<class T>inline void write(T x)
	{
		int g=0;
		if(x<0) x=-x,putchar('-');
		do { G[++g]=x%10;x/=10; } while(x);
		for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
	}
};
using namespace oi;
#define N 150010
#define S 500
int n,m;
int val[N];
int sq;
int ans[S][S];
int main()
{
	freopen("3396.in","r",stdin);
	//freopen(".out","w",stdout);
	n=read();
	m=read();
	sq=sqrt(n);
	for(int i=1;i<=n;i++) val[i]=read();
	for(int i=1;i<=sq;i++)
	{
		for(int j=1;j<=n;j++)
		{
			ans[i][j%i]+=val[j];
		}
	}
	char op;
	int x,y;
	while(m--)
	{
		oi::cin>>op>>x>>y;
		if(op=='A')
		{
			if(x<=sq)
			{
				write(ans[x][y]);
			}
			else
			{
				int ans=0;
				for(int i=y;i<=n;i+=x) ans+=val[i];
				write(ans);
			}
		}
		else
		{
			for(int i=1;i<=sq;i++)
			{
				ans[i][x%i]+=y-val[x];
			}
			val[x]=y;
		}
	}
	
	
	return 0;
}
原文地址:https://www.cnblogs.com/Vanilla-chan/p/14609248.html