思路

splay维护序列的hash值即可

因为有rev操作,还要维护反串的hash值

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
unsigned long long my_pow[600000];
const int base=131;
struct Node{
unsigned long long hashx,hashx_rev;
int son[2],inv,sz,val,fa;
}SPT[600000];
int Nodecnt,root,a[600000],len,n,m;
void get_my_pow(void){
my_pow[0]=1;
for(int i=1;i<=500000;i++)
my_pow[i]=my_pow[i-1]*base;
}
void init(void){
Nodecnt=root=len=0;
memset(SPT,0,sizeof(SPT));
memset(a,0,sizeof(a));
}
void pushup(int o){
SPT[o].sz=SPT[SPT[o].son[0]].sz+SPT[SPT[o].son[1]].sz+1;
SPT[o].hashx=SPT[SPT[o].son[0]].hashx*my_pow[SPT[SPT[o].son[1]].sz+1]+SPT[o].val*my_pow[SPT[SPT[o].son[1]].sz]+SPT[SPT[o].son[1]].hashx;
SPT[o].hashx_rev=SPT[SPT[o].son[1]].hashx_rev*my_pow[SPT[SPT[o].son[0]].sz+1]+SPT[o].val*my_pow[SPT[SPT[o].son[0]].sz]+SPT[SPT[o].son[0]].hashx_rev;
}
void pushdown(int o){
if(o&&SPT[o].inv){
if(SPT[o].son[0]){
swap(SPT[SPT[o].son[0]].son[0],SPT[SPT[o].son[0]].son[1]);
SPT[SPT[o].son[0]].inv^=1;
swap(SPT[SPT[o].son[0]].hashx,SPT[SPT[o].son[0]].hashx_rev);
}
if(SPT[o].son[1]){
swap(SPT[SPT[o].son[1]].son[0],SPT[SPT[o].son[1]].son[1]);
SPT[SPT[o].son[1]].inv^=1;
swap(SPT[SPT[o].son[1]].hashx,SPT[SPT[o].son[1]].hashx_rev);
}
SPT[o].inv^=1;
}
}
int find(int val,int o){
if(!o)
return 0;
pushdown(o);
if(val==SPT[SPT[o].son[0]].sz+1)
return o;
else if(val<=SPT[SPT[o].son[0]].sz)
return find(val,SPT[o].son[0]);
else
return find(val-SPT[SPT[o].son[0]].sz-1,SPT[o].son[1]);
}
int new_node(int val,int fa){
int o=++Nodecnt;
SPT[o].hashx=SPT[o].hashx_rev=SPT[o].val=val;
SPT[o].inv=0;
SPT[o].sz=1;
SPT[o].fa=fa;
SPT[o].son[0]=SPT[o].son[1]=0;
return o;
}
int build(int l,int r,int f){
if(l>r)
return 0;
int mid=(l+r)>>1;
int o=new_node(a[mid],f);
SPT[o].son[0]=build(l,mid-1,o);
SPT[o].son[1]=build(mid+1,r,o);
pushup(o);
return o;
}
int isrl(int o){
return SPT[SPT[o].fa].son[1]==o;
}
void rorate(int o){
int f=SPT[o].fa;
int g=SPT[f].fa;
pushdown(f);
pushdown(o);
int which=isrl(o);
if(g)
SPT[g].son[SPT[g].son[1]==f]=o;
SPT[o].fa=g;
SPT[f].son[which]=SPT[o].son[which^1];
SPT[SPT[o].son[which^1]].fa=f;
SPT[o].son[which^1]=f;
SPT[f].fa=o;
pushup(f);
pushup(o);
}
void splay(int o,int goal){
for(int f;(f=SPT[o].fa)!=goal;rorate(o))
if(SPT[f].fa!=goal)
rorate(isrl(f)==isrl(o)?f:o);
if(!goal)
root=o;
}
void debug(int o){
if(!o)
return;
pushdown(o);
debug(SPT[o].son[0]);
if(SPT[o].val>=0&&SPT[o].val<=1)
printf("%d",SPT[o].val);
else
printf(" %d ",SPT[o].val);
debug(SPT[o].son[1]);
}
void insert(int p,int c){
len++;
int t=new_node(c,0);
int lx=p,rx=p+1;
int lxx=find(lx+1,root),rxx=find(rx+1,root);
splay(lxx,0);
splay(rxx,lxx);
pushdown(root);
pushdown(SPT[root].son[1]);
SPT[SPT[root].son[1]].son[0]=t;
SPT[t].fa=SPT[root].son[1];
pushup(SPT[root].son[1]);
pushup(root);
}
void del(int p){
len--;
int lx=p-1,rx=p+1;
int lxx=find(lx+1,root),rxx=find(rx+1,root);
splay(lxx,0);
splay(rxx,lxx);
pushdown(root);
pushdown(SPT[root].son[1]);
SPT[SPT[root].son[1]].son[0]=0;
pushup(SPT[root].son[1]);
pushup(root);
}
void rev(int l,int r){
int lx=l-1,rx=r+1;
int lxx=find(lx+1,root),rxx=find(rx+1,root);
splay(lxx,0);
splay(rxx,lxx);
pushdown(root);
pushdown(SPT[root].son[1]);
int o=SPT[SPT[root].son[1]].son[0];
SPT[o].inv^=1;
swap(SPT[o].son[0],SPT[o].son[1]);
swap(SPT[o].hashx,SPT[o].hashx_rev);
}
bool check(int p1,int p2,int x){
if(x==0)
return true;
unsigned long long hash1,hash2;
{
int lx=p1-1,rx=p1+x;
int lxx=find(lx+1,root),rxx=find(rx+1,root);
splay(lxx,0);
splay(rxx,lxx);
pushdown(root);
pushdown(SPT[root].son[1]);
hash1=SPT[SPT[SPT[root].son[1]].son[0]].hashx;
}
{
int lx=p2-1,rx=p2+x;
int lxx=find(lx+1,root),rxx=find(rx+1,root);
splay(lxx,0);
splay(rxx,lxx);
pushdown(root);
pushdown(SPT[root].son[1]);
hash2=SPT[SPT[SPT[root].son[1]].son[0]].hashx;
}
return hash1==hash2;
}
int lcp(int p1,int p2){
int l=0,r=min(len-p1+1,len-p2+1),ans=0;
while(l<=r){
int mid=(l+r)>>1;
if(check(p1,p2,mid))
ans=mid,l=mid+1;
else
r=mid-1;
}
return ans;
}
int main(){
get_my_pow();
while(scanf("%d %d",&n,&m)==2){
init();
len=n;
for(int i=2;i<=n+1;i++){
char c=getchar();
while(c!='0'&&c!='1')
c=getchar();
a[i]=c-'0';
}
a[1]=-0x3f3f3f3f;
a[n+2]=0x3f3f3f3f;
root=build(1,n+2,0);
for(int i=1;i<=m;i++){
int opt,p1,p2,c;
scanf("%d",&opt);
if(opt==1){
scanf("%d %d",&p1,&c);
insert(p1,c);
}
else if(opt==2){
scanf("%d",&p1);
del(p1);
}
else if(opt==3){
scanf("%d %d",&p1,&p2);
rev(p1,p2);
}
else{
scanf("%d %d",&p1,&p2);
printf("%d\n",lcp(p1,p2));
}
}
}
return 0;
}

UVA11996 Jewel Magic的更多相关文章

  1. Jewel Magic UVA - 11996 || bzoj1014: [JSOI2008]火星人prefix

    Jewel Magic UVA - 11996 这是一道用splay/非旋treap做的题(这里用的是非旋treap) 1/2/3是splay/非旋treap的常规操作.对于操作4,可以用哈希法求LC ...

  2. UVa 11996 Jewel Magic (splay + Hash + 二分)

    题意:给定一个长度为n的01串,你的任务是依次执行如表所示的m条指令: 1 p c 在第p个字符后插入字符,p = 0表示在整个字符串之前插入2 p 删除第p个字符,后面的字符往前移3 p1 p2反转 ...

  3. UVA - 11996 Jewel Magic (Treap+二分哈希)

    维护一个01序列,一共四种操作: 1.插入一个数 2.删除一个数 3.反转一个区间 4.查询两个后缀的LCP 用Splay或者Treap都可以做,维护哈希值,二分求LCP即可. 注意反转序列的时候序列 ...

  4. UVA 11996 Jewel Magic —— splay、序列的分裂与合并、LCP的哈希算法

    #include <cstdio> #include <cstdlib> #include <iostream> #include <algorithm> ...

  5. Ceph Jewel 10.2.3 环境部署

    Ceph 测试环境部署 本文档内容概要 测试环境ceph集群部署规划 测试环境ceph集群部署过程及块设备使用流程 mon节点扩容及osd节点扩容方法 常见问题及解决方法 由于暂时没有用到对象存储,所 ...

  6. BestCoder Round #25 1002 Harry And Magic Box [dp]

    传送门 Harry And Magic Box Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/ ...

  7. Codeforces CF#628 Education 8 D. Magic Numbers

    D. Magic Numbers time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  8. [8.3] Magic Index

    A magic index in an array A[0...n-1] is defined to be an index such that A[i] = i. Given a sorted ar ...

  9. Python魔术方法-Magic Method

    介绍 在Python中,所有以"__"双下划线包起来的方法,都统称为"Magic Method",例如类的初始化方法 __init__ ,Python中所有的魔 ...

随机推荐

  1. Python 字符串的索引

    字符串是字符的有序集合,可以通过其位置来获得具体的元素.在 python 中,字符串中的字符是通过索引来提取的,索引从 0 开始. python 可以取负值,表示从末尾提取,最后一个为 -1,倒数第二 ...

  2. Python全栈-JavaScript】jQuery工具

    jQuery工具 一.jQuery.browser.version 显示当前 IE 浏览器版本号. if ( $.browser.msie ) alert( $.browser.version ); ...

  3. Alibaba, I'm interested in you.

    Working for Alibaba is an aspiration for some. For other it’s the possibility of lucrative stock opt ...

  4. C语言扫盲及深化学习

    c语言特点: (1)效率高 (2)控制性强 (3)硬件亲和性好 (4)可移植性高 一.关于注释 c语言中注释不能嵌套,因此注释代码时一定要注意源代码中是否已经存在注释.要从逻辑上删除一段代码,利用预编 ...

  5. 常用sql 集合记录整理

    select 'truncate table ' + Name + ';' from sysobjects where xtype='U' order by name asc; -- 查询出指定库的 ...

  6. Applet学习教程(一):applet+dwr 实现

    后台代码 import java.applet.Applet; import java.util.HashMap; import java.util.Map; import netscape.java ...

  7. [LeetCode] 63. Unique Paths II_ Medium tag: Dynamic Programming

    A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...

  8. Java数组之二维数组

    Java中除了一维数组外,还有二维数组,三维数组等多维数组.本文以介绍二维数组来了解多维数组. 1.二维数组的基础 二维数组的定义:二维数组就是数组的数组,数组里的元素也是数组. 二维数组表示行列二维 ...

  9. datetime模块处理时间

    python常用的处理时间的库有:datetime,time,calendar.datetime库包括了date(储存日期:(年.月.日),time(储存时间:(小时.分.秒和微秒),timedelt ...

  10. python可以提高程序执行速度N倍你知道吗?

    1.1.Numba的约5分钟指南 Numba是Python的即时编译器,它最适用于使用NumPy数组和函数以及循环的代码.使用Numba的最常用方法是通过其装饰器集合,可以应用于您的函数来指示Numb ...