题目链接:可重集
显然这种题就是用各种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;
}