CodeForces 580 E.Kefa and Watch(hash+线段树)

来源:互联网 发布:淘宝限时抢购 编辑:程序博客网 时间:2024/05/16 15:28

Description
给出一个长度为n的数字串s,两种操作:
1 l r c:把s串中区间[l,r]中所有数字都变成c
2 l r d:查询子串[l,r]的是否以d为周期
注:一个串s以d为子串指的是d<=|s|且对任意1<=i<=|s|-d有s[i]=s[i+d]
Input
第一行三个整数n,m,k分别表示串长,第一种操作数和第二种操作数,之后一个长度为n的数字串n,最后m+k行每行一个操作
(1<=n<=1e5,1<=m+k<=1e5,1<=l<=r<=n,0<=c<=9,1<=d<=r-l+1)
Output
对于每次2操作,如果子串[l,r]以d为周期则输出YES,否则输出NO
Sample Input
3 1 2
112
2 2 3 1
1 1 3 8
2 1 2 1
Sample Output
NO
YES
Solution
线段树维护hash值用来判断子串是否相等,判断[L,R]是否以d为周期时,令len=R-L+1
一. d > len,显然无解
二. d = len,显然有解
三. d < len,令k=len/d,s=len%d,
(1) k = 1,那么只要[L,R-d]和[L+d,R]相等即可
(2) k > 1,如果s=0,那么只需要[L,L+(k-1)*d-1]和[R-(k-1)*d+1,R]相等即可,若s!=0,那么还需要[L,L+s-1]和[R-s+1,R]相等
Code

#include<cstdio>#include<iostream>#include<cstring>#include<algorithm>#include<cmath>#include<vector>#include<queue>#include<map>#include<set>#include<ctime>using namespace std;typedef long long ll;#define INF 0x3f3f3f3f#define mod 1000000007#define x 10007#define maxn 444444ll f[maxn],sf[maxn];void init(){    f[0]=1;    for(int i=1;i<maxn;i++)f[i]=f[i-1]*x%mod;    sf[0]=0;    for(int i=1;i<maxn;i++)sf[i]=(sf[i-1]+f[i])%mod;}char s[maxn];#define ls (t<<1)#define rs ((t<<1)|1)ll Sum[maxn],Cover[maxn];void push_up(int l,int r,int t){    int mid=(l+r)/2;    Sum[t]=(Sum[ls]+Sum[rs]*f[mid-l+1]%mod)%mod;}void build(int l,int r,int t){    Sum[t]=Cover[t]=0;    if(l==r)    {        Sum[t]=f[1]*(s[l]-'0'+1)%mod;        return ;    }    int mid=(l+r)/2;    build(l,mid,ls),build(mid+1,r,rs);    push_up(l,r,t); }void push_down(int l,int r,int t){    if(Cover[t])    {        int mid=(l+r)/2;        Cover[ls]=Cover[rs]=Cover[t];        Sum[ls]=sf[mid-l+1]*Cover[t]%mod;        Sum[rs]=sf[r-mid]*Cover[t]%mod;        Cover[t]=0;    }}void update(int L,int R,int l,int r,int t,int v){    if(L<=l&&r<=R)    {        Sum[t]=sf[r-l+1]*v%mod;        Cover[t]=v;        return ;    }    push_down(l,r,t);    int mid=(l+r)/2;    if(L<=mid)update(L,R,l,mid,ls,v);    if(R>mid)update(L,R,mid+1,r,rs,v);    push_up(l,r,t);}ll query(int L,int R,int l,int r,int t){    if(L>R)return 0;    if(L<=l&&r<=R)return Sum[t];    push_down(l,r,t);    int mid=(l+r)/2,len=mid-max(l,L)+1;    ll ans1=-1,ans2=-1;    if(L<=mid)ans1=query(L,R,l,mid,ls);    if(R>mid)ans2=query(L,R,mid+1,r,rs);    if(~ans1&&~ans2)return (ans1+ans2*f[len]%mod)%mod;    if(~ans1)return ans1;    return ans2;}ll Solve(int n,int l,int r,int d){    int len=r-l+1;    if(len==d)return 1;    if(len<d)return 0;    int k=len/d,s=len%d;    ll t1,t2;    if(k==1)    {        t1=query(l,r-d,1,n,1);        t2=query(l+d,r,1,n,1);        return t1==t2;    }    if(len%d)    {        t1=query(l,l+s-1,1,n,1);        t2=query(r-s+1,r,1,n,1);        if(t1!=t2)return 0;    }    t1=query(l,l+(k-1)*d-1,1,n,1);    t2=query(r-(k-1)*d+1,r,1,n,1);    return t1==t2;}int main(){    init();    int n,m,k;    while(~scanf("%d%d%d",&n,&m,&k))    {        scanf("%s",s+1);        build(1,n,1);        m+=k;        while(m--)        {            int op,l,r,d;            scanf("%d%d%d%d",&op,&l,&r,&d);            if(op==1)update(l,r,1,n,1,d+1);            else printf("%s\n",Solve(n,l,r,d)?"YES":"NO");        }    }    return 0;}
阅读全文
0 0
原创粉丝点击