题目传送门:洛谷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]火星人的更多相关文章

  1. 洛谷 P4036 [JSOI2008]火星人(splay+字符串hash)

    题面 洛谷 题解 首先,我们知道求最长公共前缀可以用二分答案+hash来求 因为有修改操作, 考虑将整个字符串的hash值放入splay中 接着就是splay的基本操作了 Code #include& ...

  2. 洛谷 P1198 [JSOI2008]最大数

    洛谷 P1198 [JSOI2008]最大数 题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. ...

  3. [BZOJ 3039&洛谷P4147]玉蟾宫 题解(单调栈)

    [BZOJ 3039&洛谷P4147]玉蟾宫 Description 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地. ...

  4. 洛谷P1198 [JSOI2008]最大数(单点修改,区间查询)

    洛谷P1198 [JSOI2008]最大数 简单的线段树单点问题. 问题:读入A和Q时,按照读入一个字符会MLE,换成读入字符串就可以了. #include<bits/stdc++.h> ...

  5. 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$ ...

  6. 「线段树」「单点修改」洛谷P1198 [JSOI2008]最大数

    「线段树」「单点修改」洛谷P1198 [JSOI2008]最大数 题面描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数, ...

  7. 洛谷P1198 [JSOI2008]最大数(BZOJ.1012 )

    To 洛谷.1198 最大数 题目描述 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值. 限制:L不超过当 ...

  8. 洛谷P1198 [JSOI2008]最大数

    P1198 [JSOI2008]最大数 267通过 1.2K提交 题目提供者该用户不存在 标签线段树各省省选 难度提高+/省选- 提交该题 讨论 题解 记录 最新讨论 WA80的戳这QwQ BZOJ都 ...

  9. BZOJ1015或洛谷1197 [JSOI2008]星球大战

    BZOJ原题链接 洛谷原题链接 发现正着想毫无思路,所以我们可以考虑倒着思考,把摧毁变成建造. 这样很容易想到用并查集来维护连通块,问题也变的很简单了. 建原图,先遍历一遍所有边,若某条边的两端点未被 ...

随机推荐

  1. 每日一问(常用的集合接口和类有哪些【二】)—最常用的集合ArrayList类

    本人在曾经的数年编程生涯中,使用的最多的就是ArrayList类了,原因也非常简单.ArrayList类可以是最直接符合集合这一概念的类了,当然这种说法只是我的个人之见.ArrayList可以说是一个 ...

  2. GPU并行编程小结

    http://peghoty.blog.163.com/blog/static/493464092013016113254852/ http://blog.csdn.net/augusdi/artic ...

  3. 【XSY1841】Intervals

    Description 在一个长度为m的序列中选出n个区间,这些区间互不包含,且至少有一个区间的左端点为x. 问有多少种方案,注意交换两个区间的顺序视为不同方案. ​ 答案很大,输出模10000000 ...

  4. 【Cf Edu #47 G】Allowed Letters

    这个题大概就是每一个位置都有一个能填字符的限制(一个点集),给出已有的$n$个字符,问能填出的最小字典序的字符串. 总体思路是贪心,每一位尽量选最小的字符. 关键在于判断在某位选了一个字符后,接下来的 ...

  5. 所以到底什么是 Growth Hacking?

    Growth hacking 在硅谷的确是有快被用坏的趋势,之所以在大陆的互联网创业圈里还没有普及开来,我想一个是由于这个词并没有对应的中文解释,没有一个能够找到一个相对完美的解释,就像 “hack” ...

  6. Android打包 & Gradle用法

    Ref: Maven仓库上查插件最新版本号The Central Repository Search Enginehttp://search.maven.org/#search%7Cga%7C1%7C ...

  7. C++实现两个大整数的相加(考虑到负数异常情况)

    实现两个大整数的相加,首先应该排除直接使用int和long long的方法,这些方法很容易溢出,这里为了方便(是否可以使用更精简的结构存储?)采用char来存储整数,整体思路如下: 1. 对于整数n和 ...

  8. python学习(十九)常见的第三方库

    原文链接:http://www.limerence2017.com/2017/12/28/python19/#more 介绍几个python中常见的第三方库. Pillow Pillow简称PIL,是 ...

  9. linux join命令

    http://note.youdao.com/noteshare?id=151c4844cac74e9b08c5dc954a1a4967

  10. 利用 Dijit 组件框架打造丰富的用户界面

    原文出处:Joe Lennon 从头开始学习 Dojo,第 3 部分 利用 Dijit 组件框架打造丰富的用户界面 Dijit 是什么? Dijit 是 Dojo 工具包的富组件用户界面库.这些组件完 ...