【bzoj1014】 JSOI2008—火星人prefix
http://www.lydsy.com/JudgeOnline/problem.php?id=1014 (题目链接)
题意
给出一个字符串,要求维护这些操作:询问后缀x与后缀y的LCQ(最长公共前缀),在第k个字符后插入一个字符,将第k个字符改成另一个字符。
Solution
对于修改与插入操作,我们用splay维护。考虑怎么求解LCQ。
我们可以将字符串hash,然后平衡树上每一个节点的hash值就代表的该区间的hash值,毫无疑问,这是可以向上更新的。于是问题就解决了。
细节
注意splay中update的顺序。hash的进制要取好,不能比一位上的数范围小。hash值相乘的时候记得开long long。
代码
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define inf 2147483640
#define MOD 9875321
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout);
using namespace std; const int maxn=150010;
int tr[maxn][2],fa[maxn],id[maxn],size[maxn];
int v[maxn],h[maxn],bin[maxn];
int n,rt,sz,q;
char s[maxn]; void update(int k) {
int l=tr[k][0],r=tr[k][1];
size[k]=size[l]+size[r]+1;
h[k]=h[l]+(LL)v[k]*bin[size[l]]%MOD+(LL)bin[size[l]+1]*h[r]%MOD;
h[k]%=MOD;
}
void rotate(int x,int &k) {
int y=fa[x],z=fa[y],l,r;
l=tr[y][1]==x;r=l^1;
if (y==k) k=x;
else tr[z][tr[z][1]==y]=x;
fa[x]=z;fa[y]=x;fa[tr[x][r]]=y;
tr[y][l]=tr[x][r];tr[x][r]=y;
update(y);update(x);
}
void splay(int x,int &k) {
while (x!=k) {
int y=fa[x],z=fa[y];
if (y!=k) {
if ((tr[z][0]==y) ^ (tr[y][0]==x)) rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
int find(int k,int x) {
int l=tr[k][0],r=tr[k][1];
if (size[l]+1==x) return k;
else if (size[l]>=x) return find(l,x);
else return find(r,x-size[l]-1);
}
void insert(int k,int val) {
int x=find(rt,k+1),y=find(rt,k+2);
splay(x,rt);splay(y,tr[x][1]);
int z=++sz;tr[y][0]=z;fa[z]=y;v[z]=val;
update(z);update(y);update(x);
}
int query(int k,int val) {
int x=find(rt,k),y=find(rt,k+val+1);
splay(x,rt);splay(y,tr[x][1]);
return h[tr[y][0]];
}
int solve(int x,int y) {
int l=1,r=min(sz-x,sz-y)-1,ans=0;
while (l<=r) {
int mid=(l+r)>>1;
if (query(x,mid)==query(y,mid)) l=mid+1,ans=mid;
else r=mid-1;
}
return ans;
}
void build(int l,int r,int f) {
if (l>r) return;
int mid=(l+r)>>1,now=id[mid],last=id[f];
if (l==r) {
v[now]=h[now]=s[mid]-'a'+1;
fa[now]=last;size[now]=1;
tr[last][mid>=f]=now;
return;
}
build(l,mid-1,mid);build(mid+1,r,mid);
v[now]=s[mid]-'a'+1;fa[now]=last;update(now);
tr[last][mid>=f]=now;
}
int main() {
scanf("%s",s+2);
n=strlen(s+2);
bin[0]=1;for (int i=1;i<maxn;i++) bin[i]=bin[i-1]*31%MOD;
for (int i=1;i<=n+2;i++) id[i]=i;
build(1,n+2,0);rt=(n+3)>>1;sz=n+2;
scanf("%d",&q);
while (q--) {
int x,y;char ch[10];
scanf("%s",ch);
scanf("%d",&x);
if (ch[0]=='Q') scanf("%d",&y),printf("%d\n",solve(x,y));
if (ch[0]=='R') {
scanf("%s",ch);
x=find(rt,x+1);splay(x,rt);
v[rt]=ch[0]-'a'+1;update(rt);
}
if (ch[0]=='I') scanf("%s",ch),insert(x,ch[0]-'a'+1);
}
return 0;
}
【bzoj1014】 JSOI2008—火星人prefix的更多相关文章
- [BZOJ1014][JSOI2008]火星人prefix
[BZOJ1014][JSOI2008]火星人prefix 试题描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字 ...
- BZOJ1014 JSOI2008 火星人prefix 【非旋转Treap】*
BZOJ1014 JSOI2008 火星人prefix Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符 ...
- 2018.06.28 BZOJ1014 [JSOI2008]火星人prefix(非旋treap+hash)
[JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MB Submit: 8951 Solved: 2860 Description 火星 ...
- bzoj千题计划106:bzoj1014 [JSOI2008]火星人prefix
http://www.lydsy.com/JudgeOnline/problem.php?id=1014 两个后缀的最长公共前缀:二分+hash 带修改带插入:splay维护 #include< ...
- [BZOJ1014] [JSOI2008] 火星人prefix (splay & 二分答案)
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...
- bzoj1014: [JSOI2008]火星人prefix splay+hash+二分
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...
- [bzoj1014](JSOI2008)火星人 prefix (Splay维护哈希)
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀. 比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 ...
- BZOJ1014[JSOI2008]火星人prefix(splay维护hash)
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...
- BZOJ1014: [JSOI2008]火星人prefix(splay 二分 hash)
题意 题目链接 Sol 一眼splay + 二分hash,不过区间splay怎么写来着呀 试着写了两个小时发现死活不对 看了一下yyb的代码发现自己根本就不会splay.... // luogu-ju ...
- bzoj1014: [JSOI2008]火星人prefix(splay+hash+二分)
题目大意:一个字符串三个操作:①求两个后缀的LCP②插入一个字符③修改一个字符. 前几天刚学了hash+二分求lcp,就看到这题. 原来splay还能这么用?!原来splay模板这么好写?我以前写的s ...
随机推荐
- P3376 【模板】网络最大流
P3376 [模板]网络最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点 ...
- mysql查看数据库和表的占用空间大小
mysql查看数据库和表的占用空间大小 第一部分-任务 将线上db,导出后,导入到office db 一. 两种方案: 1,将数据直接从online-->office,通过mysqldump ...
- Java应用程序项目的打包与发行(run.bat形式)
参考: http://www.iteye.com/topic/57312 背景: 以前一直都是在eclipse上面创建应用程序,每次要要运行的时候都要打开eclipse, 直到有个同事叫我帮忙写一个应 ...
- TextBox自定义控件
首先来一发图: 今天主要说的textBox内部给予提示: 使用自定义控件方式:TextBoxTip继承TextBox 利用TextBox的背景画刷功能 VisualBrush是一种比较特殊的笔刷,它的 ...
- 误人子弟的网络,谈谈HTTP协议中的短轮询、长轮询、长连接和短连接
引言 最近刚到公司不到一个月,正处于熟悉项目和源码的阶段,因此最近经常会看一些源码.在研究一个项目的时候,源码里面用到了HTTP的长轮询.由于之前没太接触过,因此LZ便趁着这个机会,好好了解了一下HT ...
- js中什么时候回考虑用call或者apply
这里我说出自己的浅薄的理解,希望大家可以共鸣! call一些装逼的用法: call的用法通常在两个地方会用到, 1.需要加一个层的时候,也可以不准确的说继承的时候,继承是继承父类的属性或者方法,而ao ...
- Windows系统防火墙用法
1.按下“Win+X”组合键呼出系统快捷菜单,点击打开“控制面板”: 2.将“查看方式”修改为[大图标],然后点击“Windows 防火墙”: 3.在防火墙窗口左侧点击“高级设置”:(若防火墙未开启, ...
- Recommending branded products from social media -RecSys 2013-20160422
1.Information publication:RecSys 2013 author:zhengyong zhang 2.What 是对上一篇论文的拓展:利用社交媒体中用户信息 对用户购买的类别排 ...
- scrollHeight,scrollLeft,offsetHeight,offsetLeft
scrollHeight:内部元素的绝对高度,包含内部元素的隐藏的部分scrollWidth:内部元素的绝对宽度,包含内部元素的隐藏的部分 scrollLeft:设置或获取位于对象左边界和窗口中目前可 ...
- Go--避免SQL注入
避免SQL注入 什么是SQL注入 SQL注入攻击(SQL Injection),简称注入攻击,是Web开发中最常见的一种安全漏洞.可以用它来从数据库获取敏感信息,或者利用数据库的特性执行添加用户,导出 ...