题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1014

用splay维护字符串,每个点记录子树的哈希值,然后二分查询。

二分不是把两个点的哈希值拿出来二分!因为取模了所以不能还原;因为splay维护了字符串,所以二分答案后把对应一段转出来看看哈希值一不一样就行了。

如果一开始不是用给出的序列直接建一个树(就是递归 l,mid-1 和 mid+1,r 那样的),而是像我一开始一样一个一个往进插入的话,不知为何过不了呢。

有些卡时间。据说%mod会T,于是用 unsigned long long 自然溢出。

用 nxt 找后继的时候要先把对象旋转到根才行。

幂也要预处理以防超时。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define ll unsigned long long
using namespace std;
const int N=2e5+,base=;
int n,tot,c[N][],fa[N],rt,siz[N];
ll val[N],sm[N],pw[N];
char ch[N];
int init()
{
pw[]=;
for(int i=;i<=N-;i++) pw[i]=pw[i-]*base;
}
void pshp(int cr)
{
int ls=c[cr][],rs=c[cr][];
siz[cr]=siz[ls]+siz[rs]+; val[cr]=(val[rs]*base+sm[cr])*pw[siz[ls]]+val[ls];
}
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y];
if(y==k) k=x;
else c[z][y==c[z][]]=x;
int d=(x==c[y][]);
fa[x]=z; fa[y]=x; fa[c[x][!d]]=y;
c[y][d]=c[x][!d]; c[x][!d]=y;
pshp(y); pshp(x);
}
void splay(int x,int &k)
{
while(x!=k)
{
int y=fa[x],z=fa[y];
if(y!=k)
{
if((x==c[y][])^(y==c[z][]))
rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
int find(int p)
{
int cr=rt;
while(cr)
{
if(siz[c[cr][]]+==p)return cr;
else if(siz[c[cr][]]+<p)
{
p-=siz[c[cr][]]+;
cr=c[cr][];
}
else cr=c[cr][];
}
}
int nxt(int cr)
{
cr=c[cr][];
while(c[cr][]) cr=c[cr][];
return cr;
}
void insert(int p,int v)
{
int d=find(p); splay(d,rt);
int x=nxt(d); splay(x,c[rt][]);
siz[++tot]=; val[tot]=sm[tot]=v;
fa[tot]=x; c[x][]=tot;
pshp(x); pshp(d);
}
void mdfy(int p,int v)
{
int d=find(p); splay(d,rt);
sm[d]=v; pshp(d);
}
ll cz(int u,int v)
{
splay(u,rt);
int k=find(v);
splay(k,c[rt][]);
return val[c[k][]];
}
void query(int u,int v)
{
int l=,r=min(tot-u,tot-v);
int ans=;
int x=find(u-), y=find(v-);
while(l<=r)
{
int mid=l+r>>;
if(cz(x,u+mid)==cz(y,v+mid)) ans=mid,l=mid+;
else r=mid-;
}
printf("%d\n",ans);
}
void build(int l,int r,int lst,bool fx)
{
if(l>r) return;
int mid=l+r>>;
int cr=++tot; fa[cr]=lst; c[lst][fx]=cr;
sm[cr]=ch[mid]-'a'+;
if(l==r) {val[cr]=sm[cr]; siz[cr]=; return;}
build(l,mid-,cr,); build(mid+,r,cr,);
pshp(cr);
}
int main()
{
init();
scanf("%s",ch+); n=strlen(ch+);
ch[]='a'; ch[n+]='a'; n+=;
build(,n,,); rt=; c[][]=;
scanf("%d",&n);
for(int i=,x,d;i<=n;i++)
{
cin>>ch[];
if(ch[]=='I')
{
scanf("%d %c",&x,&ch[]);
d=ch[]-'a'+; insert(x+,d);
}
if(ch[]=='R')
{
scanf("%d %c",&x,&ch[]);
d=ch[]-'a'+; mdfy(x+,d);
}
if(ch[]=='Q')
{
scanf("%d%d",&x,&d);
query(x+,d+);
}
}
return ;
}

bzoj 1014 [JSOI2008]火星人prefix——splay+哈希的更多相关文章

  1. BZOJ 1014: [JSOI2008]火星人prefix [splay 二分+hash] 【未完】

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 6243  Solved: 2007[Submit] ...

  2. BZOJ 1014: [JSOI2008]火星人prefix Splay+二分

    1014: [JSOI2008]火星人prefix 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1014 Description 火星人 ...

  3. BZOJ 1014: [JSOI2008]火星人prefix( splay + hash )

    用splay维护序列, 二分+hash来判断LCQ.. #include<bits/stdc++.h> using namespace std; typedef unsigned long ...

  4. BZOJ 1014 [JSOI2008]火星人prefix (Splay + Hash + 二分)

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 8112  Solved: 2569[Submit] ...

  5. BZOJ 1014 [JSOI2008]火星人prefix | Splay维护哈希值

    题目: 题解: #include<cstdio> #include<algorithm> #include<cstring> typedef long long l ...

  6. BZOJ 1014 [JSOI2008]火星人prefix (splay+二分答案+字符串hash)

    题目大意:维护一个字符串,支持插入字符和替换字符的操作,以及查询该字符串两个后缀的最长公共前缀长度 乍一看以为是后缀数组,然而并没有可持久化后缀数组(雾) 看题解才知道这是一道splay题,首先要对s ...

  7. bzoj 1014: [JSOI2008]火星人prefix hash && splay

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3154  Solved: 948[Submit][ ...

  8. 求帮看!!!!BZOJ 1014 [JSOI2008]火星人prefix

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4164  Solved: 1277[Submit] ...

  9. [BZOJ 1014] [JSOI2008] 火星人prefix 【Splay + Hash】

    题目链接:BZOJ - 1014 题目分析 求两个串的 LCP ,一种常见的方法就是 二分+Hash,对于一个二分的长度 l,如果两个串的长度为 l 的前缀的Hash相等,就认为他们相等. 这里有修改 ...

随机推荐

  1. mac异常删除管理员账户恢复操作

    重新启动电脑,同时按下command+s键进入命令行方式 待系统加载完成后顺序输入以下命令: /sbin/mount -uaw rm var/db/.applesetupdone reboot 待系统 ...

  2. sql的一些知识_函数_汇总数据

    汇总数据 avg()---------求平均数 值得注意的是:avg()只能用于一个列的平均值查询,多个列的平均值请使用多个avg() avg()忽略null值 count()-------计数(指定 ...

  3. 百科知识 华为手机P7如何更换电池

    参考下面 教程 https://item.jd.com/3265516.html  

  4. Hibernate中的条件查询完毕类

    Hibernate中的条件查询有下面三个类完毕: 1.Criteria:代表一次查询 2.Criterion:代表一个查询条件 3.Restrictions:产生查询条件的工具类

  5. 非常不错的ajax原理总结

    在工作中用了Ajax N多次了,也看过一些相关方面的书籍,也算是认识了它,但是一直没有认真总结和整理过相关的东东,失败!近有闲情,将之总结如下:[名称]Ajax是Asynchronous JavaSc ...

  6. 关于ASP.NET MVC中Response.Redirect和RedirectToAction的BUG (跳转后继续执行后面代码而不结束进程)以及处理方法

    关于ASP.NET MVC中Response.Redirect和RedirectToAction的BUG (跳转后继续执行后面代码而不结束进程)以及处理方法   在传统的ASP.NET中,使用Resp ...

  7. Spring Cloud(十二):Spring Cloud Zuul 限流详解(附源码)(转)

    前面已经介绍了很多zuul的功能,本篇继续介绍它的另一大功能.在高并发的应用中,限流往往是一个绕不开的话题.本文详细探讨在Spring Cloud中如何实现限流. 在 Zuul 上实现限流是个不错的选 ...

  8. Unity3D总结:关于射线碰撞

    方法一:Physics.Raycast 光线投射 1.static function Raycast (origin : Vector3, direction : Vector3, distance  ...

  9. 转载---- 使用opencv源码自己编制android so库的过程

    http://blog.csdn.net/lantishua/article/details/21182965 工作需要,在Android上使用OpenCV.opencv当前的版本(2.4.8)已经有 ...

  10. Java ClassLoader详解(转载)

    Java ClassLoader详解 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一.它使得 Java 类可以被动态加载到 Java 虚拟机中并执行.类加载器从 JDK ...