线段树+哈希【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 ...
随机推荐
- 解决在linux安装网易云音乐无法点击图标打开
一下内容转载自:https://blog.csdn.net/Handoking/article/details/81026651 似乎linux下无法直接打开网易云音乐的原因是图标自带的启动脚本中没有 ...
- OScached页面缓存知识总结一
OSCache页面缓存 什么是OSCache? OSCache标记库由OpenSymphony设计,它是一种开创性的JSP定制标记应用,提供了在现有JSP页面之内实现快速内存缓冲的功能.OSCache ...
- RabbitMQ与Spring集成
RabbitMQ服务端安装: https://blog.csdn.net/hzw19920329/article/details/53156015 与Spring集成 https://www.cnbl ...
- GXC 钱包部署
参考: [ 官方 wiki ] 基于 Ubuntu 的 GXC 部署 基础环境 OS: Ubuntu gxc: 官方 [ release 最新版本 ] 下载 release 包(ubuntu) cd ...
- python学习笔记(七)之列表
列表:是一个加强版的数组,什么东西都可以往里面放. 创建列表 创建一个普通列表: >>> member = ['operating system', 'data structure' ...
- Mojo_1_第一个简单例子
use Mojolicious::Lite; #根目录,Get方法打开 #正接显示文本text get '/' => sub{ my $service = shift; $service-> ...
- 通过or注入py脚本
代码思路 1.主要还是参考了别人的代码,确实自己写的和别人写的出路很大,主要归咎还是自己代码能力待提高吧. 2.将功能集合成一个函数,然后通过*args这个小技巧去调用.函数的参数不是argv的值,但 ...
- 数据结构--Avl树的创建,插入的递归版本和非递归版本,删除等操作
AVL树本质上还是一棵二叉搜索树,它的特点是: 1.本身首先是一棵二叉搜索树. 2.带有平衡条件:每个结点的左右子树的高度之差的绝对值最多为1(空树的高度为-1). 也就是说,AVL树,本质上 ...
- 安全测试===黑客攻击常用cmd命令大全
黑客常用命令大全net user heibai lovechina /add 加一个heibai的用户密码为lovechina net localgroup Administrators heibai ...
- Spring,tk-mapper源码阅读
Mybatis的源码学习(一): 前言: 结合spring本次学习会先从spring-mybatis开始分析 在学习mybatis之前,应该要对spring的bean有所了解,本文略过 先贴一下myb ...