1. 程式人生 > >Kefa and Watch CodeForces - 580E

Kefa and Watch CodeForces - 580E

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;
}