题目: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. 每天进步一点点——Linux中的线程局部存储(二)

    转载请说明出处:http://blog.csdn.net/cywosp/article/details/26876231     在Linux中另一种更为高效的线程局部存储方法,就是使用keyword ...

  2. 小胖学PHP总结4-----PHP的字符串操作

    1.字符串连接 字符串是通过半角句号"."来连接的.能够把两个或两个以上的字符串连接成一个字符串. 2.去除字符串首尾空格和特殊字符 PHP中提供了trim()函数去除字符串左右两 ...

  3. swift学习_xcode6搭建

    首先是环境搭建 , 我的是苹果系统 , 我是个穷小子. 8k的电脑离我比較遥远. 自己动手的黑苹果 . 总价1k, 学习够用了即可.期间也学到了非常多东西 . 就是穷人仅仅能发时间去换钱了, 一直在考 ...

  4. 【每日Scrum】第六天(4.27) TD学生助手Sprint2站立会议

    站立会议 组员 昨天 今天 困难 签到 刘铸辉 (组长) 今天和楠哥做了课程事件和日历表操作的例子,并尝试做时间表和日历表的数据库设计 Y 刘静 今天开始编辑自己项目中的日历管理 编辑程序,能够在日历 ...

  5. HDU 2102 A计划 (BFS)

    A计划 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  6. impdp因致命错误终止 ORA-7445 [kpodpals]

    基本要素 前天好不easy成功给用户把数据全库导出,今天用户又告知导出的数据无法导入,首先就问用户有什么错误提示,给我的回答是就一个'作业"SYSTEM"."SYS_IM ...

  7. vue-导入静态文件

    vue导入静态文件不用像网上说的那么麻烦,其实跟普通Django项目导入类似,vue项目中有一个static文件,将你的静态文件放入到里面,然后引入就好 导入的时候和普通Django程序类似:↓ &l ...

  8. Django-form组件补充

    首先来看一个用户登录的实例 from django.forms import Form from django.forms import fields from django.forms import ...

  9. gdb调试段错误及使用

    在编程调试中,经常出现段错误,此时可用gdb调试.具体方法为注册段错误信号处理函数,在处理函数中启动gdb.具体代码如下: void segv_handler(int no) { ]; ]; FILE ...

  10. ssh 保持连接

    ssh 保持连接 使用 ssh 登陆到云主机上,一段时间没有操作终端,会发现 ssh 连接断了,终端无响应. 配置 ssh 客户端,使其以一定间隔时间向 sshd 服务端发送心跳包,可解决此问题. / ...