http://codeforces.com/problemset/problem/580/E
两种操作 一是将区间全部改为某个数字 二是询问一个区间内的数字串是否具有周期性
大体思路是 线段树维护区间哈希值 设周期为t 先查[l,l+t-1] [l+t,l+3t-1] [l+3t,l+7t-1]...这些段 看两个上一段拼起来是否等于当前段 再用同意方法反过来查右边 两边肯定在中间会合 单词查询复杂度logn*logn 但是会有特殊情况就是左右两边正好“相切” 需要再查一下最左边和最右边的一个周期长度的区间值是否相等 如果区间长度不是t的整数倍 就特判一下余数
这个题卡ull 得用大素数 以后记住再也不用ull了。。
去年做到的这套题 当时就想 这e题说的什么玩意 是人做的吗 现在再看已经很快就能有思路 并且还能写出来 虽然花了差不多一上午 但起码说明自己还是有点长进的吧 要退役了发点牢骚。。
#include
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const int maxn=1e5+10;
ll pre[10][maxn],decm[maxn];
ll lef[4*maxn],rgt[4*maxn];
int laz[4*maxn];
int n,m,k,q;
char ch[maxn];
void init()
{
ll i,j,t;
t=255;
for(i=0;i<10;i++){
for(j=1;j<=100000;j++) pre[i][j]=((t*pre[i][j-1])%mod+i+'0')%mod;
}
decm[0]=1;
for(i=1;i<=100000;i++) decm[i]=(t*decm[i-1])%mod;
}
void change(int val,int len,int cur)
{
lef[cur]=rgt[cur]=pre[val][len];
laz[cur]=val;
}
void pushup(int l,int r,int cur)
{
int m;
m=(l+r)/2;
lef[cur]=(lef[2*cur]+(lef[2*cur+1]*decm[m-l+1])%mod)%mod;
rgt[cur]=((rgt[2*cur]*decm[r-m])%mod+rgt[2*cur+1])%mod;
}
void pushdown(int l,int r,int cur)
{
int m;
if(laz[cur]!=-1){
m=(l+r)/2;
change(laz[cur],m-l+1,2*cur);
change(laz[cur],r-m,2*cur+1);
laz[cur]=-1;
}
}
void build(int l,int r,int cur)
{
int m;
laz[cur]=-1;
if(l==r){
lef[cur]=rgt[cur]=ch[l-1];
return;
}
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
pushup(l,r,cur);
}
void update(int pl,int pr,int val,int l,int r,int cur)
{
int m;
if(pl<=l&&r<=pr){
change(val,r-l+1,cur);
return;
}
pushdown(l,r,cur);
m=(l+r)/2;
if(pl<=m) update(pl,pr,val,l,m,2*cur);
if(pr>m) update(pl,pr,val,m+1,r,2*cur+1);
pushup(l,r,cur);
}
ll query(int tp,int pl,int pr,int l,int r,int cur)
{
ll res1,res2,res;
int m;
if(pl<=l&&r<=pr){
if(tp==0) return lef[cur];
else return rgt[cur];
}
pushdown(l,r,cur);
m=(l+r)/2;
if(pl<=m) res1=query(tp,pl,pr,l,m,2*cur);
else res1=0;
if(pr>m) res2=query(tp,pl,pr,m+1,r,2*cur+1);
else res2=0;
if(tp==0) res=(res1+(res2*decm[max(0,m-max(l,pl)+1)])%mod)%mod;
else res=((res1*decm[max(0,min(r,pr)-m)])%mod+res2)%mod;
return res;
}
int main()
{
ll gou,res;
int i,op,pl,pr,l,r,val,len,f0,f1,f2,f3;
init();
scanf("%d%d%d",&n,&m,&k);
scanf("%s",ch);
q=m+k;
build(1,n,1);
while(q--){
scanf("%d%d%d%d",&op,&pl,&pr,&val);
if(op==1) update(pl,pr,val,1,n,1);
else{
l=pl,r=pr-(pr-pl+1)%val;
gou=query(0,l,l+val-1,1,n,1);
i=l+val,len=2*val,f0=1;
while(i+len-1<=r){
gou=((gou*decm[len/2])%mod+gou)%mod;
res=query(0,i,i+len-1,1,n,1);
if(res!=gou){
f0=0;
break;
}
i+=len,len*=2;
}
gou=query(1,r-val+1,r,1,n,1);
i=r-val,len=2*val,f1=1;
while(i-len+1>=l){
gou=((gou*decm[len/2])%mod+gou)%mod;
res=query(1,i-len+1,i,1,n,1);
if(res!=gou){
f1=0;
break;
}
i-=len,len*=2;
}
if(query(1,l,l+val-1,1,n,1)==query(1,r-val+1,r,1,n,1)) f2=1;
else f2=0;
if(f0&&f1&&f2){
if((pr-pl+1)%val){
if(query(0,l,l+(pr-pl+1)%val-1,1,n,1)==query(0,r+1,r+(pr-pl+1)%val,1,n,1)) f3=1;
else f3=0;
}
else f3=1;
if(f3) printf("YES\n");
else printf("NO\n");
}
else printf("NO\n");
}
}
return 0;
}