#树状数组#洛谷 6688 可重集
分析
也就是排序之后的差分数组相同,考虑用树状数组维护区间和,
但是这样很容易被Hack,考虑维护质数的\(a_i\)次幂的和,
判断本质相同直接用区间和相减与区间长度相除求出相差的次数,
直接判断整体乘上这个质数次方是否相等即可
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
const int N=1000011;
typedef unsigned long long ull;
const ull base=331,mod=998244353;
ull H[N],a[N],b[N],C[N],c[N]; int n,Q;
inline ull iut(){
rr ull ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline ull mo(ull x,ull y){return x+y>=mod?x+y-mod:x+y;}
inline void Update(int x,ull y){for (;x<=n;x+=-x&x) C[x]=mo(C[x],y);}
inline ull Query(int l,int r){
rr ull ans=0; --l;
for (;r>l;r-=-r&r) ans=mo(ans,C[r]);
for (;l>r;l-=-l&l) ans=mo(ans,mod-C[l]);
return ans;
}
inline void update(int x,ull y){for (;x<=n;x+=-x&x) c[x]+=y;}
inline ull query(int l,int r){
rr ull ans=0; --l;
for (;r>l;r-=-r&r) ans+=c[r];
for (;l>r;l-=-l&l) ans-=c[l];
return ans;
}
signed main(){
n=iut(),Q=iut(),H[0]=1;
for (rr int i=1;i<N;++i) H[i]=H[i-1]*base%mod;
for (rr int i=1;i<=n;++i)
a[i]=iut(),b[i]=H[a[i]];
for (rr int i=1;i<=n;++i) c[i]=c[i-1]+a[i];
for (rr int i=n;i;--i) c[i]-=c[i&(i-1)];
for (rr int i=1;i<=n;++i) C[i]=mo(C[i-1],b[i]);
for (rr int i=n;i;--i) C[i]=mo(C[i],mod-C[i&(i-1)]);
for (rr int i=1;i<=Q;++i){
rr int z=iut();
if (!z){
rr int x=iut(); rr ull y=iut();
Update(x,mo(H[y],mod-b[x])),b[x]=H[y];
update(x,y-a[x]),a[x]=y;
}else{
rr int lx=iut(),ly=iut(),rx=iut(),ry=iut();
rr ull ans1=query(lx,ly),ans2=query(rx,ry);
rr ull Ans1=Query(lx,ly),Ans2=Query(rx,ry);
if (ans1>ans2){
ans1^=ans2,ans2^=ans1,ans1^=ans2,
Ans1^=Ans2,Ans2^=Ans1,Ans1^=Ans2;
}
Ans1=Ans1*H[(ans2-ans1)/(ly-lx+1)]%mod;
puts(Ans1==Ans2?"YES":"NO");
}
}
return 0;
}