Kefa and Watch CodeForces - 580E
阿新 • • 發佈:2018-11-23
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 <bits/stdc++.h> 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; }