【BZOJ1014】【JSOI2008】火星人prefix Splay处理区间,hash+dichotomy(二分)check出解
题意不赘述了,太清晰了。
说题解:首先依据原字符串建立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出解的更多相关文章
- bzoj1014: [JSOI2008]火星人prefix splay+hash+二分
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 二分 hash)
题意 题目链接 Sol 一眼splay + 二分hash,不过区间splay怎么写来着呀 试着写了两个小时发现死活不对 看了一下yyb的代码发现自己根本就不会splay.... // luogu-ju ...
- bzoj1014: [JSOI2008]火星人prefix splay+hash
我写的代码好像自古以来就是bzoj不友好型的 本地跑的比std快,但是交上去巧妙被卡 答案...应该是对的,拍了好久了 #include <bits/stdc++.h> #define M ...
- [BZOJ1014] [JSOI2008] 火星人prefix (splay & 二分答案)
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 ...
- [bzoj1014](JSOI2008)火星人 prefix (Splay维护哈希)
Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀. 比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 ...
- [Bzoj1014][JSOI2008]火星人prefix(无旋Treap&hash)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1014 因为涉及到增加和修改,所以后缀数组就被pass掉了,想到的就是平衡树维护hash值 ...
- [BZOJ1014][JSOI2008]火星人prefix
[BZOJ1014][JSOI2008]火星人prefix 试题描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字 ...
- BZOJ1014 JSOI2008 火星人prefix 【非旋转Treap】*
BZOJ1014 JSOI2008 火星人prefix Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符 ...
- 【BZOJ1014】[JSOI2008]火星人prefix Splay+hash
[BZOJ1014][JSOI2008]火星人prefix Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个 ...
随机推荐
- Amazon.com : The Odyssey of the Manual Toothbrusher
Amazon.com : The Odyssey of the Manual Toothbrusher The Odyssey of the Manual Toothbrusher
- poj2245Lotto(最基础的dfs)
题目链接: 啊哈哈,点我点我 思路:最開始画好搜索状态,然后找好结束条件,最好预推断当前找到的个数和能够找到的是否大于6就可以.. 题目: Lotto Time Limit: 1000MS Mem ...
- Cordova提供了一组设备相关的API,通过这组API,移动应用能够以JavaScript访问原生的设备功能,如摄像头、麦克风等。
Cordova提供了一组设备相关的API,通过这组API,移动应用能够以JavaScript访问原生的设备功能,如摄像头.麦克风等. Cordova还提供了一组统一的JavaScript类库,以及为这 ...
- zoj2059(经典dp)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1059 分析:dp[i][j]表示前i个石头组成两座塔高度差为j的较低 ...
- IDEA系统提示中文乱码问题及解决
近期要切换到IDEA开发, 在输出界面发现打印小方格, 或者乱码, 是由于字体不支持中文, 选择一个支持中文的就正常了.(由于IDEA在国内下载错误信息会用中文显示. 而之前Eclipse错误都是英文 ...
- bzoj 3519: [Zjoi2014] 消棋子 题解
[序言]在大家怀疑的眼光下,我做了一个中午和半个下午.调了一个晚上的题目总算A了! [原题] 消棋子是一个有趣的游戏.游戏在一个r * c的棋盘上进行.棋盘的每一个格 子.要么是空,要么是一种颜色的棋 ...
- SE 2014年5月6日
如图配置: 三台交换机两两相连接,构成一二层环路,同时为了保证链路的较为可靠,使用双线链接 请用自己的语言描述以上拓扑搭建的优劣势:并使用哪些技术较为合理,请描述并实施 SW3为接入层交换机,下链接三 ...
- 《Node.js In Action》笔记之流程控制
转向Javascript后,开始学习了node.js,选择的第一本书是<Node.js in Action> 将近一个月时间,断断续续看完,选几个点做下笔记 1.实现串行化流程控制 var ...
- 在配置文件(.settings、.config)中存储自定义对象
原文:在配置文件(.settings..config)中存储自定义对象 引言 我前面曾写过一篇<使用配置文件(.settings..config)存储应用程序配置>,我在其中指出“sett ...
- html中滚动栏的样式
DIV滚动栏设置 (CSS)2008/09/26 03:07div 中滚动栏的控制2008年01月06日 星期日 01:181)隐藏滚动栏<body style="overflow-x ...