线段树+哈希【CF580E】Kefa and Watch
线段树+哈希【CF580E】Kefa and Watch
Description
\(n\)个数的字符串,\(m + k\)个操作
1 l r k
把\(l - r\)赋值为\(k\)
2 l r d
询问\(l - r\)是否有长度为\(d\)的循环节\(n \leq 10^5, m + k \leq 10^5, d \leq 10\)
Input
第一行为三个整数\(n,m,k\)
第二行为一个\(n\)个数的字符串。
接下来\(m+k\)行每行对应一种操作。
Output
对于每一个\(2\)操作,如果存在,输出一行\(YES\),否则输出\(NO\)
线段树维护哈希
写起来爽,调起来更爽
我们首先预处理出\(po\)数组记录\(base^i\)(这个要用来修改及查询的。)
还要预处理出来\(val[i][j]\)代表长度为\(j\)的全部为数字\(i\)的字符串的哈希值。
然后每次区间合并的时候.
tr[o].va=(tr[ls].va\times po[len]%\ mod +tr[rs].va) %\ mod
\]
这个应该不是很难理解吧。(就类似于你\(hash\)匹配的做法。)
修改时候,我们直接赋值\(tr[o].va=val[k][len]\)即可。
需要注意的有两点:
- \(lazy\)标记初值要为\(1\),因为会存在赋值为\(0\)的情况
- 查询操作中,当前区间分别在左右两侧的时候\(tr[ls].va \times po[r-mid]\)!!
因此直接码代码就好了
还有一个神仙结论是做题的根据。
如果询问为\((l,r,d)\),则只需要判断\((l+d,r)\)和\((l,r-d)\)即可。
证明的话,我不太会.但是这是正确的。
如果这题卡单\(hash\)的话可以写双\(hash\)。稍作修改即可。不多\(BB\)了.
代码
#include<cstdio>
#include<algorithm>
#include<iostream>
#define lo long long
#define base 31
#define mod 20020303
#define R register
using namespace std;
const int gz=1e5+8;
inline void in(R int &x)
{
int f=1;x=0;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s)){x=x*10+s-'0';s=getchar();}
x*=f;
}
int n,m,K,po[gz]={1},val[10][gz];
char s[gz];
struct wc
{
int l,r,tg;
lo va;
}tr[gz<<2];
inline void pre()
{
for(R int i=1;i<gz;i++)
po[i]=po[i-1]*base%mod;
for(R int i=0;i<10;i++)
for(R int j=1;j<gz;j++)
val[i][j]=(val[i][j-1]*base%mod+i)%mod;
}
#define ls o<<1
#define rs o<<1|1
inline void up(R int o)
{
tr[o].va=(tr[ls].va*po[tr[rs].r-tr[rs].l+1]%mod+tr[rs].va%mod)%mod;
}
void build(R int o,R int l,R int r)
{
tr[o].l=l,tr[o].r=r;tr[o].tg=-1;
if(l==r)
{
tr[o].va=s[l]-'0';
return;
}
R int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
up(o);
}
inline void down(R int o)
{
if(tr[o].tg==-1)return;
R int k=tr[o].tg;
tr[ls].va=val[k][tr[ls].r-tr[ls].l+1];
tr[rs].va=val[k][tr[rs].r-tr[rs].l+1];
tr[ls].tg=tr[rs].tg=k;
tr[o].tg=-1;
}
void change(R int o,R int l,R int r,R int k)
{
if(tr[o].l==l and tr[o].r==r)
{
tr[o].tg=k;
tr[o].va=val[k][tr[o].r-tr[o].l+1];
return ;
}
down(o);
R int mid=(tr[o].l+tr[o].r)>>1;
if(r<=mid)change(ls,l,r,k);
else if(l>mid)change(rs,l,r,k);
else change(ls,l,mid,k),change(rs,mid+1,r,k);
up(o);
}
lo query(R int o,R int l,R int r)
{
if(tr[o].l==l and tr[o].r==r)return tr[o].va;
down(o);
R int mid=(tr[o].l+tr[o].r)>>1;
if(r<=mid)return query(ls,l,r);
else if(l>mid) return query(rs,l,r);
else
return ((query(ls,l,mid)%mod)*po[r-mid]%mod+query(rs,mid+1,r)%mod)%mod;//注意这里!!
}
int main()
{
pre();
in(n),in(m),in(K);
R int tt=m+K;
scanf("%s",s+1);
build(1,1,n);
for(R int opt,l,r,k;tt;tt--)
{
in(opt),in(l),in(r),in(k);
switch(opt)
{
case 1:change(1,l,r,k);break;
case 2:
{
if(r-l+1==k)
{
puts("YES");
continue;
}
puts(query(1,l,r-k)==query(1,l+k,r) ? "YES":"NO");
break;
}
}
}
}
线段树+哈希【CF580E】Kefa and Watch的更多相关文章
- 【线段树哈希】「Balkan OI 2016」Haker
1A海星 题目大意 给你一个长度为 $n$ ,由小写字母构成的字符串 $S$ 和 $Q$ 个操作,每个操作是以下 3 种之一: 1 x y k :询问当前字符串从位置 $x$ 到 $y$ 的子串与从位 ...
- cf580E. Kefa and Watch(线段树维护字符串hash)
题意 $n$个数的序列,$m + k$种操作 1.$l , r, k$把$l - r$赋值为$k$ 2.$l, r, d$询问$l - r$是否有长度为$d$的循环节 Sol 首先有个神仙结论:若询问 ...
- Codeforces Round #321 (Div. 2) E. Kefa and Watch 线段树hash
E. Kefa and Watch Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/580/prob ...
- 51Nod1553 周期串查询 字符串 哈希 线段树
原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1553.html 题目传送门 - 51Nod1553 题意 有一个串只包含数字字符.串的长度为n,下标 ...
- 线段树 + 字符串Hash - Codeforces 580E Kefa and Watch
Kefa and Watch Problem's Link Mean: 给你一个长度为n的字符串s,有两种操作: 1 L R C : 把s[l,r]全部变为c; 2 L R d : 询问s[l,r]是 ...
- [bzoj2124]等差子序列——线段树+字符串哈希
题目大意 给一个1到N的排列\(A_i\),询问是否存在\(p_i\),\(i>=3\),使得\(A_{p_1}, A_{p_2}, ... ,A_{p_len}\)是一个等差序列. 题解 显然 ...
- CF213E Two Permutations 线段树维护哈希值
当初竟然看成子串了$qwq$,不过老师的$ppt$也错了$qwq$ 由于子序列一定是的排列,所以考虑插入$1$到$m$到$n-m+1$到$n$; 如何判断呢?可以用哈希$qwq$: 我们用线段树维护哈 ...
- HDU3973 线段树 + 字符哈希
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3973 , 线段树 + 字符哈希,好题. 又学了一种新的哈希方法,hhhh~ 解法: 想法是用P进制的数 ...
- 【URAL 1989】 Subpalindromes(线段树维护哈希)
Description You have a string and queries of two types: replace i'th character of the string by char ...
随机推荐
- vijos 1448 校门外的树 树状数组
描述 校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:K=1,K=1,读入l.r表 ...
- Php扩展--protocolbuffers消息打包
安装/配置 编译安装 wge thttp://pecl.php.net/get/protocolbuffers-0.2.6.tgz tar -zxvfprotocolbuffers-0.2.6.tgz ...
- 解决nginx在记录post数据时 中文字符转成16进制的问题【转载】
1. 问题描述 nginx 在获取post数据时候,如果是中文,则转换成16进制显示在日志文件中,如下图所示. Paste_Image.png 日志格式为: log_format postdata ...
- Android开发——为移动的Paint元素指定图片的方法
源 起 最近在写一个类似“围住神经猫”的应用,现在需要给一个可以移动的Paint元素指定一张图片,如下图,要把黄点改成其他图片: Paint所在的类继承于SurfaceView,SurfaceVie ...
- Linux系统文件权限体系详解
准备工作:先简单了解Linux文件权限 在Linux系统中,ls -l 命令可以查看文件的权限,如 [zhaohuizhen@localhost Test]$ ls -l a -rw-rw-r--. ...
- HDU 2639 Bone Collector II (dp)
题目链接 Problem Description The title of this problem is familiar,isn't it?yeah,if you had took part in ...
- Problems with Ribbon/Feign/Zuul retry
原文 https://github.com/spring-cloud/spring-cloud-netflix/issues/1577 I'm using Spring Cloud Camden SR ...
- Bitmap算法应用实例(转)
关于数据库查询工作,例如有如下数据库表 要想统计所有90后的程序员该怎么做呢?用一条求交集的SQL语句即可: Select count(distinct Name) as 用户数 from table ...
- python进行机器学习(一)之数据预处理
一.加载数据 houseprice=pd.read_csv('../input/train.csv') #加载后放入dataframe里 all_data=pd.read_csv('a.csv', h ...
- parse_str
之前没有遇到过parse_str,其意思就是“把查询字符串解析到变量中”也就是$str会被解析为变量. <?php $data = "a=1&b=2";parse_s ...