思路

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. 快递单号自动识别接口API-trackingmore

    一.快递单号自动识别接口功能说明 (1)PC电脑端.移动APP或者自建网站集成物流查询功能时,只需要用户输入单号即可,不需要输入快递公司. (2)此接口可以配合Trackingmore的快递查询API ...

  2. 《图解HTTP》读书笔记(五:HTTP报文结构)

    用于 HTTP 协议交互的信息被称为 HTTP 报文. 请求端(客户端) 的HTTP 报文叫做请求报文, 响应端(服务器端) 的叫做响应报文.HTTP 报文本身是由多行(用 CR+LF 作换行符) 数 ...

  3. seafile ubuntu 安装相关

    1,各种原因,需要安装 seafile,好,开始安装. 2,参考 https://github.com/haiwen/seafile-server-installer-cn 1,Ubuntu 16.0 ...

  4. Socket断开不报错(Java)

    网上看了很多关于Socket的Demo,用起来挺好用也简单,不过都在断开连接时,都没有做好相关处理,导致每次主动断开时,会报错 如: java.net.SocketException: Socket ...

  5. vi检索

    / :检索 n    :向下执行上一步的检索 N   :向上执行上一步的检索

  6. liunx安装py.27

    liunx安装py.27 按网站(https://blog.csdn.net/u012071918/article/details/78817344) 上的教程安装py.27 1.安装依赖的库 在终端 ...

  7. 解决git冲突造成的Please move or remove them before you can merge

    git clean -d -fx “” 其中x —–删除忽略文件已经对git来说不识别的文件d —–删除未被添加到git的路径中的文件f —–强制运行如果你确定这货已经没用了,并且git status ...

  8. Spring增强代理模式

    1. 依赖注入;(掌握) 2. XML自动注入;(掌握) 3. 全注解配置;(掌握) 4. 代理模式;(掌握,难点) 依赖注入 构造参数注入 constructor-arg:构造器注入: index: ...

  9. mvc自定义分页(加页数的)(转)

    1.引言 在MVC开发中我们经常会对数据进行分页的展示.通过分页我们可以从服务端获取指定的数据来进行展示.这样既节约了数据库查询的时间也节约了网络传输的数据量.在MVC开发中使用的比较多的应该是MVC ...

  10. HDFS组件性能调优:数据平衡

    生产系统中什么情况下会添加一个节点呢? 1 增加存储能力 disk 2 增加计算能力 cpu mem 如果增加是的是存储能力,说明存储已接近饱和或者说过段时间就会没有剩余的空间给作业来用.新加的节点存 ...