[JSOI2008]火星人 题解
原题链接:\(luogu\)$\ \ $ \(BZOJ\)$\ \ $ \(LOJ\)
题目大意:有一个可以支持插入和修改的字符串,定义函数 \(\operatorname{LCQ(x,y)}\) 表示从 \(x\) 开始的后缀与从 \(y\) 开始的后缀的最长公共前缀。
声明变量:
\(ls\):左儿子
\(rs\):右儿子
\(val\):平衡树维护变量,此题指字符 -'a'
\(sz\):子树大小
\(rk\):对应堆值
\(hs\):哈希值,后面会讲
\(pq\):哈希对应要乘的数字
考虑既然是求最长公共前缀,当然可以通过二分长度来求,用哈希维护即可。
要支持插入和修改,很显然可以用平衡树的 \(FHQ\ Treap\) 进行区间维护。
在原先 \(FHQ\) 需要维护的五个量的基础上,加入 \(hs\),表示其子树内的 \(hash\) 值。
转移方程即为:\(hs[x]=hs[ls[x]]+val[x]\times pq[sz[ls[x]]]+hs[rs[x]]\times pq[sz[ls[x]]+1]\)
插入修改按 \(FHQ\) 原先操作即可
代码:
#include<bits/stdc++.h>
#define ls(x) pl[x].ls
#define rs(x) pl[x].rs
#define val(x) pl[x].val
#define sz(x) pl[x].sz
#define rk(x) pl[x].rk
#define hs(x) pl[x].hs
#define ull unsigned long long
using namespace std;
struct fhq{
int ls,rs,val,sz,rk;ull hs;
}pl[100005];
int fhq_fail;
ull q=1145141,pq[250005];
int make_node(int x){
int a=++fhq_fail;
pl[a]={0,0,x,1,rand(),x};
return a;
}struct fhq_treap{
int rt,x,y,z;fhq_treap(){rt=x=y=z=0;}
void pushup(int p){
sz(p)=sz(ls(p))+sz(rs(p))+1;
hs(p)=hs(ls(p))+val(p)*pq[sz(ls(p))]+hs(rs(p))*pq[sz(ls(p))+1];
}void split(int p,int a,int &x,int &y){
if(!p){x=y=0;return;}
if(sz(ls(p))<a) x=p,split(rs(p),a-sz(ls(p))-1,rs(p),y);
else y=p,split(ls(p),a,x,ls(p));pushup(p);
}int merge(int x,int y){
if(!x||!y) return x+y;
if(rk(x)<rk(y)){
rs(x)=merge(rs(x),y);
pushup(x);return x;
}ls(y)=merge(x,ls(y));
pushup(y);return y;
}void add(int a,int b){
split(rt,a,x,y);
rt=merge(merge(x,make_node(b)),y);
}void change(int a,int b){
split(rt,a,x,z);split(x,a-1,x,y);
val(y)=hs(y)=b;rt=merge(merge(x,y),z);
}ull ghs(int l,int r){
split(rt,r-1,x,z);split(x,l-1,x,y);
ull re=hs(y);rt=merge(merge(x,y),z);return re;
}
}a;int n,m;string s;
int main(){
ios::sync_with_stdio(0);cin.tie(0);
srand(19820422);cin>>s>>m;
n=s.size();pq[0]=1;
for(int i=1;i<=n+m;i++) pq[i]=pq[i-1]*q;
for(int i=0;s[i];i++) a.rt=a.merge(a.rt,make_node(s[i]-'a'));
while(m--){
char c;int x;cin>>c>>x;
if(c=='Q'){
int y;cin>>y;if(x>y) swap(x,y);
int l=1,r=sz(a.rt)-y+1,ans=0;
while(l<=r){
int mid=(l+r)/2;
if(a.ghs(x,x+mid)==a.ghs(y,y+mid))
l=mid+1,ans=mid;else r=mid-1;
}cout<<ans<<"\n";continue;
}char d;cin>>d;
if(c=='R') a.change(x,d-'a');
else a.add(x,d-'a');
}return 0;
}//Kaká
[JSOI2008]火星人 题解的更多相关文章
- [BZOJ1014][JSOI2008]火星人prefix
[BZOJ1014][JSOI2008]火星人prefix 试题描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字 ...
- 【bzoj1014】[JSOI2008]火星人prefix
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 6031 Solved: 1917[Submit] ...
- BZOJ 1014: [JSOI2008]火星人prefix Splay+二分
1014: [JSOI2008]火星人prefix 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1014 Description 火星人 ...
- JSOI2008 火星人prefix
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2918 Solved: 866[Submit][ ...
- 【BZOJ1014】[JSOI2008]火星人prefix Splay+hash
[BZOJ1014][JSOI2008]火星人prefix Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个 ...
- 1014: [JSOI2008]火星人prefix
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MB Description 火星人最近研究了一种操作:求一个字串两个后缀 ...
- BZOJ 1014: [JSOI2008]火星人prefix [splay 二分+hash] 【未完】
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 6243 Solved: 2007[Submit] ...
- bzoj 1014: [JSOI2008]火星人prefix hash && splay
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3154 Solved: 948[Submit][ ...
- 求帮看!!!!BZOJ 1014 [JSOI2008]火星人prefix
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4164 Solved: 1277[Submit] ...
- BZOJ 1014: [JSOI2008]火星人prefix( splay + hash )
用splay维护序列, 二分+hash来判断LCQ.. #include<bits/stdc++.h> using namespace std; typedef unsigned long ...
随机推荐
- Vue.js 组件注册
1.前言 本节讲述组件和2.x版本和3.x版本的注册方式 2.全局注册 2.x版本直接调用Vue.component()方法进行全局注册,所有Vue实例都能使用,包括其组件 //组件代码省略 var ...
- 自有Jar包生成Docker镜像
前言 经常会有些自己写的一些SpringBoot小项目,为了实现一些小的功能/需求,但是部署的时候,不管是生成jar包,还是war包部署到tomcat中,都容易因为需要部署的环境(比如java版本.t ...
- SafeHandle 和 Dispose
SafeHandle 和 Dispose 这是从 https://www.cnblogs.com/zeroone/p/3708112.html 复制过来的,原文的格式不够好,重新排版一下. SafeH ...
- Qt/C++音视频开发77-获取本地有哪些摄像头名称/ffmpeg命令日志方式
一.前言 上一篇文章讲使用ffmpeg函数接口去获取本地摄像头信息,这种方式只能从ffmpeg5版本开始才具备,那ffmpeg3/4只能干瞪眼?那肯定不行的,必须要想办法打通这个功能,查阅信息发现可以 ...
- 贝叶斯定律和卡尔曼滤波中,关于(e^-x)*(e^-x)的积分的计算方法
贝叶斯定律和卡尔曼滤波中,关于(e^-x)*(e^-x)的积分的计算方法: 1.用数学软件Mathmatica计算: 2.用复变函数中的留数定理计算: 3.用FFT+卷积公式计算.
- C51--05---LCD1602调试工具
一.LCD1602调试工具 单片机调试工具: 数码管 液晶屏 串口 数码管需要不断进行扫描,一旦扫描不及时就会不断闪烁,并且可显示的数据太过局限: 串口需要使用电脑进行发送指令,不易操作与携带: 所以 ...
- 《入梦》Revisited
寝室里有本<美丽新世界>(Brave New World),书页翻过灯塔里上升的螺旋阶梯,还有大概三分之一的篇幅是<重返美丽新世界>(Brave New World Rev ...
- Python 潮流周刊#85:让 AI 帮你写出更好的代码(摘要)
本周刊由 Python猫 出品,精心筛选国内外的 250+ 信息源,为你挑选最值得分享的文章.教程.开源项目.软件工具.播客和视频.热门话题等内容.愿景:帮助所有读者精进 Python 技术,并增长职 ...
- 深入理解ReentrantLock的实现原理
文章目录ReentrantLock简介AQS回顾ReentrantLock原理ReentrantLock结构非公平锁的实现原理lock方法获取锁tryRelease锁的释放公平锁的实现原理lock方法 ...
- 京东从 OpenStack 改用 Kubernetes 的始末
构建集群的历史 物理机器的时代(2004年-2014年) 在2014年之前,我们公司的应用程序都部署在物理机器上.在物理机器时代,为了给即将上线的应用程序分配物理机器,我们平均需要等上一周的时间.由于 ...