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
- CodeForces 580 E.Kefa and Watch(hash+线段树)
- Codeforces 580E Kefa and Watch 线段树+双值Hash
- codeforces 580 E. Kefa and Watch (字符串hash + 线段树)
- codeforces 580 E. Kefa and Watch(hash+线段树)
- codeforces 321# E. Kefa and Watch (线段树+字符串hash)
- CODEFORCES ROUND #321 (DIV. 2) E.Kefa and Watch(线段树+hash)
- Codeforces 580E Kefa and Watch 线段树
- Codeforces #321 E. Kefa and Watch (线段树、哈希)
- Codeforces Round #321 (Div. 2) E - Kefa and Watch(hash + 线段树)
- CODEFORCES 580E Kefa and Watch
- 查询[l,r]区间数字串是不是周期为d的串 线段树区间修改+双重hash Codeforces #321 E. Kefa and Watch
- 字符串hash+线段树 Codeforces580E Kefa and Watch
- Codeforces Round #321 Kefa and Watch(字符串哈希+线段树)
- CF#321-DIV2-E. Kefa and Watch-线段树+字符串哈希
- 【Code Forces 321E】【线段树+字符串哈希】Kefa and Watch 字符串修改 循环节判定
- codeforces580E. Kefa and Watch
- codeforces 381E Sereja and Brackets(线段树)
- Codeforces 381E Sereja and Brackets(线段树)
- Spring思维导图,让Spring不再难懂(mvc篇)
- arcgis engine 图形操作函数 (面切面)
- MIT《计算机科学数学》Introduction & Chaper01-Proofs
- 玲珑杯1144
- Python爬虫正则表达式和re模块系列之七
- CodeForces 580 E.Kefa and Watch(hash+线段树)
- 在Qt对话框类的构造函数中 退出程序
- maven打包报错如下
- java获取Mac地址
- Ubuntu下安装mdbtools并访问mdb文件
- XMAN选拔赛官方Writeup
- C语言中函数参数传递的三种方式
- ZOJ3856 Goldbach
- 06.12 cobbler无人值守安装