思路

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. oracle学习笔记第三天

    --DML(Data Manipulation Language)--insert关键字 插入 ---语法1.元祖值式插入(一次插入一条记录)---格式:insert into 表名(列名1,列名2. ...

  2. spring-data-mongodb中的MongoTemplate与MongoRepository

    springboot添加maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <a ...

  3. MFC 对话框不显示,返回-1 原因

    DoModal失败原因 1.MFC 通常对话框不显示的原因有 1 父窗口HWND无效 2 在ONINITDIALOG里用了ENDDIALOG 3 无效的对话框资源ID 4 使用没有注册的的自定义控件 ...

  4. Xamarin Forms error MSB6006: “java.exe”已退出,代码为 2 解决办法

    https://vicenteguzman.mx/2017/08/20/error-java-exe-exited-with-code-2-xamari-forms/

  5. iframe子页面与父页面元素的访问以及js变量的访问

    1.子页面访问父页面元素  parent.document.getElementById('id')和document相关的方法都可以这样用 2.父页面访问子页面元素  document.getEle ...

  6. fork()相关的源码解析

    fork()的真正执行采用的是do_fork()函数,所以下文将从do_fork()函数对fork()进行源码解析.下图是do_fork()的源码函数设计: 从上图我们可以看到do_fork()涉及到 ...

  7. 搭建apache本地服务器·Mac

    1. 打开终端,开启Apache: //开启apache: sudo apachectl start //重启apache: sudo apachectl restart //关闭apache: su ...

  8. XML文件的读取

    <?xml version="1.0" encoding="gbk"?> <!--设置编码格式为gbk--> <!DOCTYPE ...

  9. Ubuntu MariaDB PhpMyAdmin

    root@www:~# apt-get -y install phpmyadmin php-mbstring php-gettext # select which one you using (thi ...

  10. tcpdf中增加微软雅黑的正确方式

    找了很多增加字体的方式,不过提供的命令行下增加字体的命令是错误的,下面这个命令是验证过可以用的,不管是win还是linux活着mac都可以. tcpdf对中文的支持就不太好, 当然也可以支持, 比如里 ...