题目大意

  就是给你一个字符串,有三种操作,共\(m\)个

   \(Q~x~y\):询问第\(x\)个后缀和第\(y\)个后缀的LCP

   \(R~x~y\):把第\(x\)个字符改成\(y\)

   \(I~x~y\):在第\(x\)个字符后面插入一个字符\(y\)

  \(m\leq 150000,\)任何时候字符串长度\(\leq 100000\),询问个数\(\leq 10000\)

题解

  直接用平衡树维护哈希值,询问时二分答案。我用unsigned long long存回TLE,用unsigned存就能过。

  时间复杂度:\(O(q\log^2n+m\log n)\)(\(q\)为询问个数)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
using namespace std;
typedef long long ll;
typedef unsigned ui;
typedef pair<int,int> pii;
struct node
{
int v;
int k;
int ls,rs;
int sz;
ui s;
node()
{
v=k=ls=rs=sz=0;
s=0;
}
};
node a[1000010];
int cnt=0;
ui pw[1000010];
int newnode(int v)
{
cnt++;
a[cnt].v=v;
a[cnt].k=rand();
a[cnt].s=v;
a[cnt].sz=1;
return cnt;
}
void mt(int p)
{
a[p].s=a[a[p].ls].s*pw[a[a[p].rs].sz+1]+a[p].v*pw[a[a[p].rs].sz]+a[a[p].rs].s;
a[p].sz=a[a[p].ls].sz+a[a[p].rs].sz+1;
}
int merge(int x,int y)
{
if(!x||!y)
return x+y;
if(a[x].k<a[y].k)
{
a[x].rs=merge(a[x].rs,y);
mt(x);
return x;
}
else
{
a[y].ls=merge(x,a[y].ls);
mt(y);
return y;
}
}
pii split(int x,int v)
{
if(!x)
return pii();
if(v<=a[a[x].ls].sz)
{
pii s=split(a[x].ls,v);
a[x].ls=s.second;
s.second=x;
mt(x);
return s;
}
else
{
pii s=split(a[x].rs,v-a[a[x].ls].sz-1);
a[x].rs=s.first;
s.first=x;
mt(x);
return s;
}
}
char s[1000010];
int rt=0;
int n;
ui gethash(int l,int r)
{
if(l>r)
return 0;
pii s1=split(rt,r);
pii s2=split(s1.first,l-1);
ui res=a[s2.second].s;
s1.first=merge(s2.first,s2.second);
rt=merge(s1.first,s1.second);
return res;
}
int query(int x,int y)
{
int l=0;
int r=min(n-x+1,n-y+1);
while(l<r)
{
int mid=(l+r+1)>>1;
if(gethash(x,x+mid-1)==gethash(y,y+mid-1))
l=mid;
else
r=mid-1;
}
return l;
}
void insert(int x,int v)
{
pii s1=split(rt,x);
s1.first=merge(s1.first,newnode(v));
rt=merge(s1.first,s1.second);
n++;
}
void change(int x,int v)
{
pii s1=split(rt,x);
pii s2=split(s1.first,x-1);
a[s2.second].s=a[s2.second].v=v;
s1.first=merge(s2.first,s2.second);
rt=merge(s1.first,s1.second);
}
int main()
{
freopen("bzoj1014.in","r",stdin);
freopen("bzoj1014.out","w",stdout);
srand(12700);
int i,m;
pw[0]=1;
for(i=1;i<=1000000;i++)
pw[i]=pw[i-1]*127;
scanf("%s",s+1);
n=strlen(s+1);
for(i=1;i<=n;i++)
rt=merge(rt,newnode(s[i]-'a'+1));
scanf("%d",&m);
int x,y;
for(i=1;i<=m;i++)
{
scanf("%s",s+1);
if(s[1]=='Q')
{
scanf("%d%d",&x,&y);
printf("%d\n",query(x,y));
}
else if(s[1]=='R')
{
scanf("%d%s",&x,s+1);
change(x,s[1]-'a'+1);
}
else
{
scanf("%d%s",&x,s+1);
insert(x,s[1]-'a'+1);
}
}
return 0;
}

【JSOI2008】火星人prefix 哈希 非旋转treap的更多相关文章

  1. BZOJ1014 JSOI2008 火星人prefix 【非旋转Treap】*

    BZOJ1014 JSOI2008 火星人prefix Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符 ...

  2. 2018.06.28 BZOJ1014 [JSOI2008]火星人prefix(非旋treap+hash)

    [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MB Submit: 8951 Solved: 2860 Description 火星 ...

  3. 【bzoj1014】: [JSOI2008]火星人prefix 平衡树-字符串-hash-二分

    [bzoj1014]: [JSOI2008]火星人 用平衡树维护字符串的hash 然后询问的时候二分一下就好了 /* http://www.cnblogs.com/karl07/ */ #includ ...

  4. 1014: [JSOI2008]火星人prefix

    1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MB Description 火星人最近研究了一种操作:求一个字串两个后缀 ...

  5. 【bzoj1014】[JSOI2008]火星人prefix

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

  6. 【bzoj3224】Tyvj 1728 普通平衡树 01Trie姿势+平衡树的四种姿势 :splay,旋转Treap,非旋转Treap,替罪羊树

    直接上代码 正所谓 人傻自带大常数 平衡树的几种姿势:  AVL Red&Black_Tree 码量爆炸,不常用:SBT 出于各种原因,不常用. 常用: Treap 旋转 基于旋转操作和随机数 ...

  7. [BZOJ1014][JSOI2008]火星人prefix

    [BZOJ1014][JSOI2008]火星人prefix 试题描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字 ...

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

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

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

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

随机推荐

  1. python-入门的第一个爬虫例子

    前言: 此文为大家入门爬虫来做一次简单的例子,让大家更直观的来了解爬虫. 本次我们利用 Requests 和正则表达式来抓取豆瓣电影的相关内容. 一.本次目标: 我们要提取出豆瓣电影-正在上映电影名称 ...

  2. Git_GitHub详解

    Git和Github详细教程 一  概述 说到Git和Github,前几天我们知道微软以75亿美元收购全球最大的代码托管和写作平台GitHub,而GitHub是全球最大的代码仓库,很多开发人员都将代码 ...

  3. 一个6亿的表a,一个3亿的表b,通过外间tid关联,你如何最快的查询出满足条件的第50000到第50200中的这200条数据记录

    1.如果A表TID是自增长,并且是连续的,B表的ID为索引 select * from a,b where a.tid = b.id and a.tid>500000 limit 200; 2. ...

  4. Liunx 简单的命令说明

    cd命令在linux中用来切换或者进入目录,路径还分为相对路径和绝对路径 cd 命令:切换当前目录至其他目录 cd /:加上斜杠表示是进入到根目录. pwd命令:查看当前路径. ()cd 进入用户主目 ...

  5. Java中JDK和JRE的区别是什么?它们的作用分别是什么?

    JDK和JRE是Java开发和运行工具,其中JDK包含了JRE,但是JRE是可以独立安装的,它们在Java开发和运行的时候起到不同的作用~ 1.JDK JDK是Java Development Kit ...

  6. git rebase的用法

    改变基 一个git库,开发人员在master分支的Bcommit的时候,创建了一个dev分支,此时Bcommit是dev分支的基,然后分别进行两个分支的开发. 进行到master提交了Dcommit, ...

  7. Tomcat Cluster

    Tomcat群集配置| Tomcat集群| MuleSofthttps://www.mulesoft.com/tcat/tomcat-cluster Tomcat Clustering - A Ste ...

  8. 994.Contiguous Array 邻近数组

    描述 Given a binary array, find the maximum length of a contiguous subarray with equal number of 0 and ...

  9. 剑指offer(18)二叉搜索树的后续遍历

    题目: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果.如果是则输出Yes,否则输出No.假设输入的数组的任意两个数字都互不相同. 思路: 以最后一个节点为根,从头往后找到第一个大于根 ...

  10. Maven 项目 查找指定包的引用位置