bzoj 1014: 洛谷 P4036: [JSOI2008]火星人
题目传送门:洛谷P4036。
题意简述:
有一个字符串,支持插入字符,修改字符。
每次需要查询两个后缀的LCP长度。
最终字符串长度\(\le 100,\!000\),修改和询问的总个数\(\le 150,\!000\),查询操作\(\le 10,\!000\)。
题解:
由后缀和LCP可以想到后缀数组或后缀自动机,但是它们都无法插入或修改。
考虑到LCP可以通过二分+哈希的方式来计算,考虑维护区间的哈希值。
这里使用平衡树无旋Treap来维护区间的哈希值。
一次修改\(O(\log n)\),一次询问\(O(\log^2 n)\)。
bzoj时限略卡,用了自然溢出才过。
#include<bits/stdc++.h>
using namespace std;
#define Bse 19260817u
unsigned Pow[]; char Str[];
int N,Q;
int ls[],rs[],siz[],pri[],val[],cnt,Root;
unsigned ha[]; unsigned ran(){static unsigned x=;return x^=x<<,x^=x>>,x^=x<<;} void combine(int id){
siz[id]=siz[ls[id]]++siz[rs[id]];
ha[id]=Pow[siz[rs[id]]+]*ha[ls[id]]+Pow[siz[rs[id]]]*val[id]+ha[rs[id]];
} int Merge(int rt1,int rt2){
if(!rt1) return rt2;
if(!rt2) return rt1;
if(pri[rt1]>=pri[rt2]){
rs[rt1]=Merge(rs[rt1],rt2);
combine(rt1);
return rt1;
}
else{
ls[rt2]=Merge(rt1,ls[rt2]);
combine(rt2);
return rt2;
}
} void Split(int rt,int k,int&rt1,int&rt2){
if(!rt) {rt1=rt2=; return;}
if(k<=siz[ls[rt]]){
Split(ls[rt],k,rt1,rt2);
ls[rt]=rt2;
combine(rt);
rt2=rt;
}
else{
Split(rs[rt],k-siz[ls[rt]]-,rt1,rt2);
rs[rt]=rt1;
combine(rt);
rt1=rt;
}
} void Insert(int pos,int v){
val[++cnt]=v, ha[cnt]=v, pri[cnt]=ran(), siz[cnt]=;
int rt1,rt2;
Split(Root,pos,rt1,rt2);
Root=Merge(Merge(rt1,cnt),rt2);
} void Change(int pos,int v){
int rt1,rt2,rt3,rt4;
Split(Root,pos-,rt1,rt2);
Split(rt2,,rt3,rt4);
val[rt3]=v; combine(rt3);
Root=Merge(Merge(rt1,rt3),rt4);
} unsigned chk(int pos,int len){
int rt1,rt2,rt3,rt4;
Split(Root,pos-,rt1,rt2);
Split(rt2,len,rt3,rt4);
unsigned D=ha[rt3];
Root=Merge(Merge(rt1,rt3),rt4);
return D;
} int main(){
Pow[]=; for(int i=;i<=;++i) Pow[i]=Pow[i-]*Bse;
scanf("%s",Str+);
N=strlen(Str+);
for(int i=;i<=N;++i)
Insert(i-,Str[i]);
scanf("%d",&Q);
for(int i=;i<=Q;++i){
int x,y; char opt[];
scanf("%s",opt);
if(*opt=='Q'){
scanf("%d%d",&x,&y);
int l=, r=N-max(x,y)+, mid, ans=;
while(l<=r){
mid=l+r>>;
if(chk(x,mid)==chk(y,mid)) ans=mid, l=mid+;
else r=mid-;
}
printf("%d\n",ans);
}
else if(*opt=='R'){
scanf("%d%s",&x,opt);
Change(x,*opt);
}
else if(*opt=='I'){
scanf("%d%s",&x,opt);
Insert(x,*opt);
++N;
}
}
return ;
} // luogu P4036 - Fhq-Treap + hash. 18:20 ~ 19:03
bzoj 1014: 洛谷 P4036: [JSOI2008]火星人的更多相关文章
- 洛谷 P4036 [JSOI2008]火星人(splay+字符串hash)
题面 洛谷 题解 首先,我们知道求最长公共前缀可以用二分答案+hash来求 因为有修改操作, 考虑将整个字符串的hash值放入splay中 接着就是splay的基本操作了 Code #include& ...
- 洛谷 P1198 [JSOI2008]最大数
洛谷 P1198 [JSOI2008]最大数 题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. ...
- [BZOJ 3039&洛谷P4147]玉蟾宫 题解(单调栈)
[BZOJ 3039&洛谷P4147]玉蟾宫 Description 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地. ...
- 洛谷P1198 [JSOI2008]最大数(单点修改,区间查询)
洛谷P1198 [JSOI2008]最大数 简单的线段树单点问题. 问题:读入A和Q时,按照读入一个字符会MLE,换成读入字符串就可以了. #include<bits/stdc++.h> ...
- P4036 [JSOI2008]火星人(splay+hash+二分)
P4036 [JSOI2008]火星人 Splay维护hash,查询二分 $a[x].vl=a[lc].vl*ha[a[rc].sz+1]+a[x].w*ha[a[rc].sz]+a[rc].vl$ ...
- 「线段树」「单点修改」洛谷P1198 [JSOI2008]最大数
「线段树」「单点修改」洛谷P1198 [JSOI2008]最大数 题面描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数, ...
- 洛谷P1198 [JSOI2008]最大数(BZOJ.1012 )
To 洛谷.1198 最大数 题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. 限制:L不超过当 ...
- 洛谷P1198 [JSOI2008]最大数
P1198 [JSOI2008]最大数 267通过 1.2K提交 题目提供者该用户不存在 标签线段树各省省选 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 WA80的戳这QwQ BZOJ都 ...
- BZOJ1015或洛谷1197 [JSOI2008]星球大战
BZOJ原题链接 洛谷原题链接 发现正着想毫无思路,所以我们可以考虑倒着思考,把摧毁变成建造. 这样很容易想到用并查集来维护连通块,问题也变的很简单了. 建原图,先遍历一遍所有边,若某条边的两端点未被 ...
随机推荐
- Dcoker中启动mysql,并实现root远程访问
mysql容器的运行 下载mysql 5.7.19的镜像 docker pull mysql:5.7.19 运行mysql容器,端口映射为 10036 docker run --name mysql5 ...
- P3293 [SCOI2016]美味
题目描述 一家餐厅有 n 道菜,编号 1...n ,大家对第 i 道菜的评价值为 ai(1<=i<=n).有 m 位顾客,第 i 位顾客的期望值为 bi,而他的偏好值为 xi .因此,第 ...
- 整理:python的二维数组操作
Python中初始化一个5 x 3每项为0的数组,最好方法是: multilist = [[0 for col in range(5)] for row in range(3)] 如果初始化一个二维数 ...
- CF1083C Max Mex 线段树
题面 CF1083C Max Mex 题解 首先我们考虑,如果一个数x是某条路径上的mex,那么这个数要满足什么条件? 1 ~ x - 1的数都必须出现过. x必须没出现过. 现在我们要最大化x,那么 ...
- kafka-connect-hive sink实现要点小结
kafka-connect-hive sink插件实现了以ORC和Parquet两种方式向Hive表中写入数据.Connector定期从Kafka轮询数据并将其写入HDFS,来自每个Kafka主题的数 ...
- 51nod 1421 最大MOD值 | 暴力
题面 有一个a数组,里面有n个整数.现在要从中找到两个数字(可以是同一个) ai,aj ,使得 ai mod aj 最大并且 ai ≥ aj. Input 单组测试数据. 第一行包含一个整数n,表示数 ...
- Android studio gradle配置完整版(转)
Android studio gradle配置完整版https://my.oschina.net/u/1471093/blog/539075 Android studio 自定义打包apk名 - pe ...
- loj6070【山东集训第一轮Day4】基因
题解: 分块对每个块的起点$st[i]$到$n$做一次回文自动机; 由于子串的回文自动机是原串的子图,所以并不需要重新构图,在原来的图上做即可: 做的时候记录某个终点的本质不同的回文串和$sum[i] ...
- python之旅:迭代器、生成器、面向过程编程
1.什么是迭代器? 1.什么是迭代器 迭代的工具 什么是迭代? 迭代是一个重复的过程,每一次重复都是基于上一次结果而进行的 # 单纯的重复并不是迭代 while True: print('=====& ...
- python 冒泡法 排序
冒泡排序 冒泡排序(Bubble Sort):重复地遍历要排序的数列,依次比较两个元素,如果他们的顺序不符就把他们交换过来.就像气泡一样,需要排序的元素通过比较.交换位置,一点一点浮到对应的位置. 个 ...