Description
给定一个长度为 (n) 的序列,有 (q) 次操作,每次给定一个 ([l,r]) 将 (a_l,...,a_r) 每个元素 (+1),或者给定 (x,y,l) 询问 (a[x..x+l-1]) 与 (a[y..y+l-1]) 是否完全相同。所有元素在任意时刻对 (65536) 取模。
Solution
暴力用 hash 维护,模数自取,如果没有溢出的情况则正常处理即可。
现在考虑如何处理溢出的情况,对于每个区间记录一个最大值,如果这个最大值 (ge 65536) 则暴力递归下去找到这个最大值并且把它修改掉。
溢出的次数保证了复杂度。
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
const int mod = 998244353;
const int bas = 137;
int n,q,t1,t2,t3,t4,a[N];
int power[N];
int mask[N];
struct SegmentTree
{
struct Node
{
int len;
int val;
int tag;
int mx;
Node operator + (const Node &x)
{
return {len+x.len, (val*power[x.len]+x.val)%mod, 0, max(mx,x.mx)};
}
} node[N*4];
void maintain(int p)
{
node[p].val%=mod;
node[p].tag%=mod;
}
void change(int p,int v)
{
node[p].val+=v*mask[node[p].len];
node[p].tag+=v;
node[p].mx+=v;
maintain(p);
}
void pushdown(int p,int l,int r)
{
if(node[p].tag!=0)
{
int t=node[p].tag;
node[p].tag=0;
change(p*2,t);
change(p*2+1,t);
}
}
void build(int p,int l,int r,int *src)
{
if(l==r)
{
node[p]={1,a[l],0,a[l]};
}
else
{
build(p*2,l,(l+r)/2,src);
build(p*2+1,(l+r)/2+1,r,src);
node[p]=node[p*2]+node[p*2+1];
}
}
void modify(int p,int l,int r,int ql,int qr)
{
if(l>qr || r<ql) return;
if(l>=ql && r<=qr)
{
change(p,1);
}
else
{
pushdown(p,l,r);
modify(p*2,l,(l+r)/2,ql,qr);
modify(p*2+1,(l+r)/2+1,r,ql,qr);
node[p]=node[p*2]+node[p*2+1];
}
}
void reduce(int p,int l,int r,int pos)
{
if(l==r)
{
node[p]={1,0,0,0};
}
else
{
pushdown(p,l,r);
if(pos<=(l+r)/2) reduce(p*2,l,(l+r)/2,pos);
else reduce(p*2+1,(l+r)/2+1,r,pos);
node[p]=node[p*2]+node[p*2+1];
}
}
void eliminate(int p,int l,int r)
{
if(node[p].mx<65536) return;
if(l==r)
{
reduce(1,1,n,l);
}
else
{
pushdown(p,l,r);
eliminate(p*2,l,(l+r)/2);
eliminate(p*2+1,(l+r)/2+1,r);
}
}
Node query(int p,int l,int r,int ql,int qr)
{
if(l>qr || r<ql) return {0,0,0,0};
if(l>=ql && r<=qr)
{
return node[p];
}
else
{
pushdown(p,l,r);
return query(p*2,l,(l+r)/2,ql,qr) + query(p*2+1,(l+r)/2+1,r,ql,qr);
}
}
int query(int ql,int qr)
{
return query(1,1,n,ql,qr).val;
}
} segtree;
signed main()
{
ios::sync_with_stdio(false);
cin>>n>>q;
power[0]=1;
for(int i=1;i<=n;i++)
{
power[i]=power[i-1]*bas%mod;
mask[i]=(mask[i-1]+power[i-1])%mod;
}
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
segtree.build(1,1,n,a);
for(int i=1;i<=q;i++)
{
int op;
cin>>op;
if(op==1)
{
int l,r;
cin>>l>>r;
segtree.modify(1,1,n,l,r);
segtree.eliminate(1,1,n);
}
else
{
int x,y,l;
cin>>x>>y>>l;
int l1=x,r1=x+l-1,l2=y,r2=y+l-1;
int b1=segtree.query(l1,r1);
int b2=segtree.query(l2,r2);
if(b1==b2) puts("yes");
else puts("no");
}
}
return 0;
}