题意不赘述了,太清晰了。

说题解:首先依据原字符串建立SPT。首尾建议多加一个空白字符。

给一个树构图,依照平衡树的前后大小顺序性质能够使它们始终维持为一个序列,而且能够通过rank找到序列的第k个。

树构造完了以后。点插入,点改动,询问神马的代码里都有具体凝视。

/*
BZOJ 1014
新手看的时候建议从main函数处開始,依照执行顺序来脑模拟。 P.S. 这个代码的hash用的是自然溢出而非取mod运算。
*/
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define N 250010
#define is(x) (son[fa[x]][1]==x)
using namespace std;
typedef unsigned long long LL;
char start[N];
int digit[N];
LL power[N]={1};
struct node
{
int root,n;
LL hash[N];
int val[N],fa[N],son[N][2],size[N];
inline void update(int p)
{
size[p]=size[son[p][0]]+size[son[p][1]]+1;
hash[p]=hash[son[p][0]]*power[size[son[p][1]]+1]+val[p]*power[size[son[p][1]]]+hash[son[p][1]];
/*此代码是得到53位制的hash值,hash[p]表示该段的hash值。想一下就非常好理解。*/
}
inline void Build(int l,int r,int mid)
{
if(l<mid)/*左边有数*/
{
int lmid=l+mid-1>>1;
Build(l,mid-1,lmid);
fa[lmid]=mid;
son[mid][0]=lmid;
}
if(mid<r)/*右边有数*/
{
int rmid=mid+1+r>>1;
Build(mid+1,r,rmid);
fa[rmid]=mid;
son[mid][1]=rmid;
}
val[mid]=digit[mid],update(mid);
/*val表示当前字符(数字版)*/
}
inline void link(int x,int y,int d){son[y][d]=x;fa[x]=y;}
inline void Rotate(int x)
{
int y=fa[x],z=fa[y],id=is(x),t=son[x][!id];
if(t)fa[t]=y;son[y][id]=t;
link(x,z,is(y));
link(y,x,!id);
update(y);
}
inline void Splay(int x,int k)
{
int y,z;
while(fa[x]!=k)
{
y=fa[x];
z=fa[y];
if(z==k){Rotate(x);break;}
if(is(x)==is(y))Rotate(y),Rotate(x);
else Rotate(x),Rotate(x);
}
update(x);
if(!k)root=x;
}
inline int Select(int rank,int k)/*找到该节点并将它旋转到k的儿子处(k=0则旋到根)*/
{
if(size[root]<rank)return -1;/*找不到*/
int x=root;
while(size[son[x][0]]+1!=rank)/*循环条件:根不是要找的节点*/
{
if(size[son[x][0]]+1>rank)x=son[x][0];
else rank=rank-size[son[x][0]]-1,x=son[x][1];
}/*已经找到要找的节点*/
Splay(x,k);
return x;
}
inline void newnode(int &x,int y,int w)
{
x=++n;
son[x][0]=son[x][1]=0;
val[x]=w;
fa[x]=y;
size[x]=1;
}
inline void Insert(int x,int p)
{
int l=Select(x,0),r=Select(x+1,l);
/*x到根。x+1到根的右子节点。即保证r的左子树为NULL*/
newnode(son[r][0],r,p);
Splay(n,0);
}
inline void Change(int x,int p){x=Select(x,0),val[x]=p,Splay(x,0);}
inline bool check(int a,int b,int len)
{
int x;
Select(a-1,0);x=Select(a+len,root);
/*把区间(此处为a開始的len个)rotate到lrt*/
if(x==-1)return 0;
LL hash1=hash[son[x][0]];
Select(b-1,0);x=Select(b+len,root);
if(x==-1)return 0;
LL hash2=hash[son[x][0]];
return hash1==hash2;
}
}tree;
void handle()
{
int i,m,l,r,mid,L,R;
char a[5];
for(int i=1;i<N;i++)power[i]=power[i-1]*53;
scanf("%s",start);
tree.n=strlen(start)+2;/*左右各添一个空白字符*/
for(int i=2;i<=tree.n-1;i++)digit[i]=start[i-2]-'a'+1;
tree.root=(1+tree.n)>>1,tree.Build(1,tree.n,1+tree.n>>1);/*建树*/
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%s",a);
/*以下l+1的缘故是由于序列左右各添了一个空白字符*/
if(a[0]=='Q')
{
scanf("%d %d",&L,&R);
l=0,r=tree.n;
while(l<r)
{/*二分出解*/
mid=l+r>>1;
if(tree.check(L+1,R+1,mid))l=mid+1;
else r=mid;
}
printf("%d\n",l-1);
}
else if(a[0]=='R')
{
scanf("%d %s",&l,a);
tree.Change(l+1,a[0]-'a'+1);
}
else
{
scanf("%d %s",&l,a);
tree.Insert(l+1,a[0]-'a'+1);
}
}
}
int main()
{
// freopen("test.in","r",stdin);
handle();
return 0;
}

【BZOJ1014】【JSOI2008】火星人prefix Splay处理区间,hash+dichotomy(二分)check出解的更多相关文章

  1. bzoj1014: [JSOI2008]火星人prefix splay+hash+二分

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...

  2. BZOJ1014[JSOI2008]火星人prefix(splay维护hash)

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...

  3. BZOJ1014: [JSOI2008]火星人prefix(splay 二分 hash)

    题意 题目链接 Sol 一眼splay + 二分hash,不过区间splay怎么写来着呀 试着写了两个小时发现死活不对 看了一下yyb的代码发现自己根本就不会splay.... // luogu-ju ...

  4. bzoj1014: [JSOI2008]火星人prefix splay+hash

    我写的代码好像自古以来就是bzoj不友好型的 本地跑的比std快,但是交上去巧妙被卡 答案...应该是对的,拍了好久了 #include <bits/stdc++.h> #define M ...

  5. [BZOJ1014] [JSOI2008] 火星人prefix (splay & 二分答案)

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...

  6. [bzoj1014](JSOI2008)火星人 prefix (Splay维护哈希)

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀. 比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 ...

  7. [Bzoj1014][JSOI2008]火星人prefix(无旋Treap&hash)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1014 因为涉及到增加和修改,所以后缀数组就被pass掉了,想到的就是平衡树维护hash值 ...

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

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

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

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

  10. 【BZOJ1014】[JSOI2008]火星人prefix Splay+hash

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

随机推荐

  1. zoj1940(三维广搜)

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=940 分析:三维其实就是六个方向地搜索,思维清晰且细心点,很快就AC了 ...

  2. Hulu面试题解答——N位数去除K个数字(解法错误sorry)

    给定一个N位数,比如12345,从里面去掉k个数字.得到一个N-k位的数.比如去掉2,4,得到135,去掉1,5.得到234.设计算法.求出全部得到的N-k位数里面最小的那一个. 写的代码例如以下,思 ...

  3. BASH Shell 简易进度条小函数

    不多说,直接上脚本. # processbar <current> <total> processbar() { local current=$1; local total=$ ...

  4. hadoop在实现kmeans算法——一个mapreduce实施

    写mapreduce程序实现kmeans算法.我们的想法可能是 1. 次迭代后的质心 2. map里.计算每一个质心与样本之间的距离,得到与样本距离最短的质心,以这个质心作为key,样本作为value ...

  5. Learning Cocos2d-x for WP8(3)——文字篇

    原文:Learning Cocos2d-x for WP8(3)--文字篇 C#兄弟篇Learning Cocos2d-x for XNA(3)——文字篇 文字,是人类文明的象征. 文字显示,可用字符 ...

  6. iis 隐藏 banner

    去微软官网下载这个补丁  http://www.microsoft.com/en-us/search/DownloadResults.aspx?q=urlscan+3.1 2.  安装urlscan_ ...

  7. Android 访问Android Wear数据层Api——同步Data Items

    Data Items它被用来同步手机和wear数据接口,一个Date Items通常包含以下几个部分: Payload 字节数组.无论你需要设置数据类型,我们同意对象序列化和反序列化,大小不能超过10 ...

  8. Multitasking Apps may only use background services for their intended purposes

    2.16 Details Your app declares support for audio in the UIBackgroundModes key in your Info.plist, bu ...

  9. hdu4635(最多加多少边,使得有向图不是强连通图)

    连边的最后肯定是两个集合x,yx集合的每个元素,到y集合中的每个元素都是单向的边x集合,和y集合都是完全图设a为x集合的点的个数, b为y集合的那么答案就是 a * b + a*(a-1) + b*( ...

  10. profile与bashrc

    /etc/profile./etc/bashrc 是系统全局环境变量设定 ~/.profile,~/.bashrc用户家文件夹下的私有环境变量设定 当登入系统时候获得一个shell进程时.其读取环境设 ...