可重集

题目链接:可重集


显然这种题就是用各种hash去做的。

如果是判断一个区间是否完全相等,我们可以给每个值换一个随机值,然后区间异或哈希。

但是现在是差分相等,如果是区间异或的话,做加法很困难。所以我们可以考虑用次幂哈希。

例如:5 = base ^ 5

这个就很好做加法了。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e6+10,mod=1e9+3,base=13333331;
int pw[N],n,q,a[N],mi[N<<2],sum[N<<2];
char *fs,*ft,buf[1<<20];
#define gc() (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<20,stdin),fs==ft))?0:*fs++;
inline int read(){
    int x=0,f=1; char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
    return x*f;
}
inline int add(int x,int y){x+=y; if(x>=mod) x-=mod; return x;}
#define mid (l+r>>1)
void change(int p,int l,int r,int x,int v){
	if(l==r){sum[p]=pw[v],mi[p]=v; return ;}
	if(x<=mid)	change(p<<1,l,mid,x,v);
	else	change(p<<1|1,mid+1,r,x,v);
	mi[p]=min(mi[p<<1],mi[p<<1|1]),sum[p]=add(sum[p<<1],sum[p<<1|1]);
}
pair<int,int> ask(int p,int l,int r,int ql,int qr){
	if(l==ql&&r==qr)	return {mi[p],sum[p]};
	if(qr<=mid)	return ask(p<<1,l,mid,ql,qr);
	else if(ql>mid) return ask(p<<1|1,mid+1,r,ql,qr);
	pair<int,int> ls=ask(p<<1,l,mid,ql,mid),rs=ask(p<<1|1,mid+1,r,mid+1,qr);
	return {min(ls.first,rs.first),add(ls.second,rs.second)};
}
signed main(){
	n=read(),q=read();	pw[0]=1;
	for(int i=1;i<N;i++)	pw[i]=1LL*pw[i-1]*base%mod;
	for(int i=1;i<=n;i++)	a[i]=read(),change(1,1,n,i,a[i]);
	for(int i=1,op,l1,r1,l2,r2;i<=q;i++){
		op=read(),l1=read(),r1=read();
		if(!op)	change(1,1,n,l1,a[l1]=r1);
		else{
			l2=read(),r2=read();
			auto ls=ask(1,1,n,l1,r1),rs=ask(1,1,n,l2,r2);
			if(ls.first>rs.first)	swap(ls,rs);
			puts((rs.second==(1LL*ls.second*pw[rs.first-ls.first]%mod))?"YES":"NO");
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43826249/article/details/107667866