[BZOJ1074] [luogu 4036] [JSOI 2008] 火星人 (二分答案+哈希+fhq treap)
[BZOJ1074] [luogu 4036] [JSOI 2008] 火星人 (二分答案+哈希+fhq treap)
题面
给出一个长度为n的字符串,m个操作,字符串仅包含小写英文字母
操作1:在k位置后插入字符v:
操作2:将k位置的字符修改为字符v
操作3:查询从该字符串中第 x个字符开始的字符串,与该字符串中第 y个字符开始的字符串,两个字串的公共前缀的长度
分析
看到动态插入和修改,考虑用fhq treap维护字符串序列。以下split指按子树大小分裂
操作1:同样split出前k个的子树x,和剩下的子树y,新建一个节点v,merge(merge(x,v),y)
操作2:split出前k-1个的子树x,k对应的子树y,和剩下的子树z,新建一个节点v,merge(merge(x,v),z)即可,y子树丢弃
操作3:考虑二分答案,然后问题就转化为查询区间[l1,r1],区间[l2,r2]是否相等。这可以通过用fhq treap,维护以x为根中序遍历得到序列的hash值,查询的时候只要split(r),split(l-1)即可
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 200000
#define prime 27
using namespace std;
typedef unsigned int ull;
ull p[maxn+5];
struct fhq_treap{
#define lson(x) (tree[x].ls)
#define rson(x) (tree[x].rs)
struct node{
int ls;
int rs;
int val;
int dat;
ull hs;//hash
int sz;
}tree[maxn+5];
int ptr=0;
int root;
void push_up(int x){
tree[x].sz=tree[lson(x)].sz+tree[rson(x)].sz+1;
tree[x].hs=tree[lson(x)].hs*p[tree[rson(x)].sz+1]+tree[x].val*p[tree[rson(x)].sz]+tree[rson(x)].hs;
//从左到右hash,相当于中序遍历
//假如左子树是ab,x是c,右子树是de,整个序列是abcde
//由于我们把abcde看成一个p进制数来hash,那么ab,c要乘上p的次方
}
int New(int val){
ptr++;
tree[ptr].ls=tree[ptr].rs=0;
tree[ptr].val=val;
tree[ptr].dat=rand();
tree[ptr].hs=val;
tree[ptr].sz=1;
return ptr;
}
int merge(int x,int y){
if(!x||!y) return x+y;
if(tree[x].dat<tree[y].dat){
tree[x].rs=merge(tree[x].rs,y);
push_up(x);
return x;
}else{
tree[y].ls=merge(x,tree[y].ls);
push_up(y);
return y;
}
}
void split(int now,int k,int &x,int &y){
if(now==0){
x=y=0;
return;
}
if(k<=tree[lson(now)].sz){
y=now;
split(tree[now].ls,k,x,tree[y].ls);
}else{
x=now;
split(tree[now].rs,k-tree[lson(now)].sz-1,tree[x].rs,y);
}
push_up(now);
}
void insert(int pos,int val){//在pos后面插入val
int x,y;
split(root,pos,x,y);
root=merge(merge(x,New(val)),y);
}
void update(int pos,int val){//把pos改成val
int x,y,z;
split(root,pos,y,z);
split(y,pos-1,x,y);
root=merge(merge(x,New(val)),z);
}
ull query(int l,int r){
int x,y,z;
ull ans;
split(root,r,y,z);
split(y,l-1,x,y);
ans=tree[y].hs;
root=merge(x,merge(y,z));
return ans;
}
#undef lson
#undef rson
}T;
int n,m;
char a[maxn+5];
bool check(int x,int y,int len){
return T.query(x,x+len-1)==T.query(y,y+len-1);
}
int bin_search(int x,int y){
int l=1,r=min(n-x+1,n-y+1);
int mid;
int ans=0;
while(l<=r){
mid=(l+r)>>1;
if(check(x,y,mid)){
ans=mid;
l=mid+1;
}else r=mid-1;
}
return ans;
}
int main(){
int x,y;
char cmd[2],val[2];
scanf("%s",a+1);
n=strlen(a+1);
p[0]=1;
for(int i=1;i<=maxn;i++) p[i]=p[i-1]*prime;
for(int i=1;i<=n;i++){
T.insert(i-1,a[i]-'a'+1);
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%s",cmd);
if(cmd[0]=='Q'){
scanf("%d %d",&x,&y);
if(x>y) swap(x,y);
printf("%d\n",bin_search(x,y));
}else if(cmd[0]=='R'){
scanf("%d %s",&x,val);
T.update(x,val[0]-'a'+1);
}else{
scanf("%d %s",&x,val);
T.insert(x,val[0]-'a'+1);
n++;
}
}
}
[BZOJ1074] [luogu 4036] [JSOI 2008] 火星人 (二分答案+哈希+fhq treap)的更多相关文章
- Luogu P2920 时间管理【二分答案】
二分答案水题. (像我这么蒻的人都能十几分钟A掉) https://www.luogu.org/problemnew/show/P2920 开始时间一定在从0到min(t[i]-s[i])的一段区间上 ...
- [Luogu P1462] 通往奥格瑞玛的道路 (二分答案+最短路径)
题面 传送门:https://www.luogu.org/problemnew/show/P1462 Solution 这道题如果去除掉经过城市的收费.那么就是裸的最短路 但是题目要求经过城市中最多的 ...
- 【Luogu】P2824排序(二分答案+线段树排序)
题目链接 震惊!两个线段树和一个线段树竟是50分的差距! 本题可以使用二分答案,二分那个位置上最后是什么数.怎么验证呢? 把原序列改变,大于等于mid的全部变成1,小于mid的全部变成0,之后线段树排 ...
- Luogu P1396 营救【最小生成树/二分答案/最短路】 By celur925
题目描述 “咚咚咚……”“查水表!”原来是查水表来了,现在哪里找这么热心上门的查表员啊!小明感动的热泪盈眶,开起了门…… 妈妈下班回家,街坊邻居说小明被一群陌生人强行押上了警车!妈妈丰富的经验告诉她小 ...
- Luogu P1638 逛画展 【二分答案】
题目描述 博览馆正在展出由世上最佳的 M 位画家所画的图画. wangjy想到博览馆去看这几位大师的作品. 可是,那里的博览馆有一个很奇怪的规定,就是在购买门票时必须说明两个数字, a和b,代表他要看 ...
- BZOJ4755 JSOI2016扭动的回文串(二分答案+哈希)
显然答案应该是由单串以某位置为中心的极长回文串继续在另一个串里拓展得到的.枚举中间位置二分答案,哈希判断即可.注意考虑清楚怎么处理偶回文,比如像manacher一样加分隔符. #include< ...
- Luogu P1462 通往奥格瑞玛的道路 二分答案+最短路
先二分答案,再跑最短路,跑的时候遇到 过路费超过二分的答案的 就不拿他更新最短路 #include<cstdio> #include<iostream> #include< ...
- JSOI 2008 火星人prefix
FROM http://www.lydsy.com/JudgeOnline/problem.php?id=1014 LCP问题 给定串 S[0..n] , 对于一对(a,b)其中0<a,b< ...
- Luogu P1083 借教室【二分答案/差分】By cellur925
题目描述 Description 在大学期间,经常需要租借教室.大到院系举办活动,小到学习小组自习讨论,都需要 向学校申请借教室.教室的大小功能不同,借教室人的身份不同,借教室的手续也不一样. 面对海 ...
随机推荐
- HTML中的marquee标签实现滚动效果
一.标签<marquee>简介 通过开始标签<marquee>和结束标签</marquee>的共同配合而实现滚动效果,<marquee>滚动的内容< ...
- Ubuntu 16.04下使用docker部署MySQL主从复制
(以下docker相关的命令,需要在root用户环境下或通过sudo提升权限来进行操作.) 首先更新 软件源 https://mirrors.tuna.tsinghua.edu.cn/help/ubu ...
- 洛谷P4391 [BOI2009]Radio Transmission 无线传输——题解
题目传送 假如我们有一个用于循环连接的最短串ans,考虑用它造出来的数据(即输入的字符串s)有什么特点.发现:ans自我连接出一个大串z后从中取出的一个子串即为s,对s造一个KMP算法中的next数组 ...
- 贪心整理&一本通1431:钓鱼题解
题目传送 (其实有一个更正经的题解) 看了许久,发现这题貌似就是一个动态规划啊,但毕竟是贪心题库里的题,还是想想用贪心解吧. 经过(借鉴大佬思路)十分复杂的思考后,终于理解出了这题的贪心思路.该题的难 ...
- iOS9 3DTouch 之 Home Screen Quick Actions
最后更新:2016-12-18 测试环境: Xcode8.1 一.前言 iOS9 已经过去一年了,3D Touch也在项目中实战过,但一直没有总结一下,现在新的项目也用到了3D Touch, 网上找了 ...
- Linux下" >/dev/null 2>&1 "详解
在学习Linux的过程中,常会看到一些终端命令或者程序中有">/dev/null 2>&1 "出现,由于已经遇到了好几次了,为了理解清楚,不妨花点时间百度或者g ...
- WIN10系统和压缩内存占用磁盘过高的解决方案(亲测有效)
系统和压缩内存磁盘占用过高的解决方案 最近一段时间玩游戏看视频经常莫名的卡顿,观察发现电脑卡的时候,WIN10进程中的"系统和压缩内存"一项占用了近100%的磁盘空间. 百度搜索到 ...
- [BZOJ4558]:[JLoi2016]方(容斥+模拟)
题目传送门 题目描述 上帝说,不要圆,要方,于是便有了这道题.由于我们应该方,而且最好能够尽量方,所以上帝派我们来找正方形上帝把我们派到了一个有N行M列的方格图上,图上一共有$(N+1)\times ...
- 《Vue前端开发手册》
序言 为了统一前端的技术栈问题,技术开发二部规定开发技术必须以Vue为主. 为了更好的规范公司的前端框架,现以我前端架构师为主,编写以下开发规范,如有不当的地方,欢迎批评教育并慢慢改善该开发文档,谢谢 ...
- js方法返回多值如何取值demo
js方法返回,如何取值?下面demo两种方法 new array 和 json 返回值 取值示例. 方法一: new array <html> <head> <meta ...