题目: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. [c++菜鸟]《Accelerate C++》读书笔记

    第0章 开始学习C++ 1.<<的行为取决于它的操作数类型,<<会把它的右操作数的字符写到左操作数所指示的流中,他是结果就是它的左操作数. 2.std::endl是一个控制器, ...

  2. 用DD-WRT自建计费WiFi热点

    架设无线网络(Wlan)向周围的用户有偿共享网络. 传统的方法,能够使用专业的无线与宽带计费网关设备和软件.比方MikroTik等. 只是,对于个人架设WiFi热点来说.这些方案太过昂贵,安装设置也很 ...

  3. 文件另存为——Autocad.doc.SaveAs

    一.前言 使用pyautocad编辑好cad图纸后,往往涉及到一个保存的问题,但是官方文档并未提及,所以只能自己来了,测试了好久,终于是找到了保存的命令和参数说明. 二.方法介绍 Autocad.do ...

  4. ubuntu 16.04 更新 gcc/g++ 4.9.2

    ubuntu 转载 2016年10月12日 :: 标签:ubuntu /g++ /gcc [html] view plain copy sudo dpkg -l g++ 最近在学C++primer , ...

  5. 怎样退出App之前唤醒还有一个App?

    郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主,捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 SDK并没 ...

  6. win10下rose2003安装与破解(图解)

    系统刷成了win10的,因为选择的是全新安装的方式,所以开发工具又得又一次安装了,rose尽管好用.但是安装破解还是有点麻烦,这里整理一下.备用,下回就不须要去网上搜索了. 安装文件下载地址:链接: ...

  7. 【上】安全HTTPS-全面具体解释对称加密,非对称加密,数字签名,数字证书和HTTPS

    一,对称加密 所谓对称加密.就是它们在编码时使用的密钥e和解码时一样d(e=d),我们就将其统称为密钥k. 对称加解密的步骤例如以下: 发送端和接收端首先要共享同样的密钥k(即通信前两方都须要知道相应 ...

  8. db2 命令

    很久没有些博客了.把以前用到的操作 DB2 的命令发表下可能有很多人已经发布了.就当是自己做下功课吧,以备有用之需. 1. 打开命令行窗口 #db2cmd 2. 打开控制中心 # db2cmd db2 ...

  9. Liquibase

    http://www.liquibase.org/documentation/index.html https://github.com/studygolang/studygolang/tree/ma ...

  10. aop学习总结一------使用jdk动态代理简单实现aop功能

    aop学习总结一------使用jdk动态代理实现aop功能 动态代理:不需要为目标对象编写静态代理类,通过第三方或jdk框架动态生成代理对象的字节码 Jdk动态代理(proxy):目标对象必须实现接 ...