#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <vector> using namespace std; typedef unsigned long long ull;
const int x = ;
const int maxn = 4e5 + ; ull xp[maxn];
int n, m;
struct Node {
Node* ch[];
int r, v, s;
int val;
ull Hush[];
int flip;
Node(int v1, int v2): v(v1), val(v2) {
r = rand();
s = ;
ch[] = ch[] = NULL;
flip = ;
Hush[] = Hush[] = val;
}
bool cmp(const int &x) const {
if(x == v) return -;
return x < v ? : ;
}
void maintain() {
s = ;
Hush[] = Hush[] = val;
if(ch[] != NULL) s += ch[]->s, Hush[] = ch[]->Hush[ch[]->flip] + val*xp[ch[]->s];
if(ch[] != NULL) Hush[] += (ch[]->Hush[ch[]->flip])*xp[s], s += ch[]->s;
int s2 = ;
if(ch[] != NULL) s2 += ch[]->s, Hush[] = ch[]->Hush[(ch[]->flip)^] + val*xp[ch[]->s];
if(ch[] != NULL) Hush[] += (ch[]->Hush[(ch[]->flip)^])*xp[s2];
}
void pushdown() {
if(flip) {
flip = ;
swap(ch[], ch[]);
if(ch[] != NULL) ch[]->flip = !ch[]->flip;
if(ch[] != NULL) ch[]->flip = !ch[]->flip;
}
}
}; void rotate(Node* &o, int d) {
Node* k = o->ch[d^]; o->ch[d^] = k->ch[d]; k->ch[d] = o;
o->maintain(); k->maintain(); o = k;
} void insert(Node* &o, int x, int val) {
if(o == NULL) o = new Node(x, val);
else {
int d = o->cmp(x);
insert(o->ch[d], x, val);
if(o->ch[d]->r > o->r) rotate(o, d^);
}
o->maintain();
}
void splay(Node* &o, int k) {
o->pushdown();
int s = o->ch[] == NULL ? : o->ch[]->s;
int d = k <= s ? : (k == s+? - : );
if(d == ) k -= s+;
if(d != -) {
splay(o->ch[d], k);
rotate(o, d^);
}
} Node * merge(Node* left, Node* right) {
splay(left, left->s);
left->ch[] = right;
left->maintain();
return left;
}
void split(Node* o, int k , Node* &left, Node* &right) {
splay(o, k);
left = o;
right = o->ch[];
o->ch[] = NULL;
left->maintain();
} void oper1(Node* &o, int p, int c) {
Node* left, *right;
Node* node = new Node(p+, c);
split(o, p+, left, right);
o = merge(merge(left, node), right);
}
void oper2(Node* &o, int p) {
Node* left, *mid, *right;
split(o, p, left, mid);
split(mid, , mid, right);
o = merge(left, right);
}
void oper3(Node* &o, int p1, int p2) {
Node *left, *mid, *right;
split(o, p1, left, mid);
split(mid, p2-p1+, mid, right);
mid->flip ^= ;
o = merge(merge(left, mid), right);
}
ull Hush_val(Node* &o, int p, int L) {
Node *left, *mid, *right;
split(o, p, left, mid);
split(mid, L, mid, right);
ull ans = mid->Hush[mid->flip];
o = merge(merge(left, mid), right);
return ans;
}
int oper4(Node* &o, int p1, int p2) {
int L = , R = min(n-p1+, n-p2+);
while(L < R) {
int M = R - (R-L)/;
int l1 = Hush_val(o, p1, M), l2 = Hush_val(o, p2, M);
if(l1 == l2) L = M;
else R = M-;
}
return L;
}
char s[maxn];
int main() {
xp[] = ;
for(int i = ; i < maxn; i++) xp[i] = xp[i-]*x;
while(scanf("%d%d", &n, &m) == ) {
scanf("%s", s);
Node* root = new Node(, );
for(int i = ; i < n; i++) {
int c = s[i] - '';
insert(root, i+, c);
}
for(int i = ; i < m; i++) {
int id, p1, p2;
scanf("%d", &id);
if(id == ) {
scanf("%d%d", &p1, &p2);
oper1(root, p1, p2);
n++;
}
if(id == ) {
scanf("%d", &p1);
oper2(root, p1);
n--;
}
if(id == ) {
scanf("%d%d", &p1, &p2);
oper3(root, p1, p2);
}
if(id == ) {
scanf("%d%d", &p1, &p2);
int ans = oper4(root, p1, p2);
printf("%d\n", ans);
}
}
}
return ;
}

UVA 11996 Jewel Magic —— splay、序列的分裂与合并、LCP的哈希算法的更多相关文章

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

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

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

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

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

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

  4. UVA - 11922 Permutation Transformer (splay)

    题目链接 题意:你的任务是根据m条指令改变排列{!,2,3,...,n}.每条指令(a,b)表示取出第a~b个元素,翻转后添加到排列的尾部.输出最终序列. 解法:splay对区间分裂合并翻转,模板题. ...

  5. BZOJ1500: [NOI2005]维修数列 [splay序列操作]【学习笔记】

    以前写过这道题了,但我把以前的内容删掉了,因为现在感觉没法看 重写! 题意: 维护一个数列,支持插入一段数,删除一段数,修改一段数,翻转一段数,查询区间和,区间最大子序列 splay序列操作裸题 需要 ...

  6. uva 1608 不无聊的序列

    uva 1608 不无聊的序列 紫书上有这样一道题: 如果一个序列的任意连续子序列中都至少有一个只出现一次的元素,则称这个序列时不无聊的.输入一个n个元素的序列,判断它是不是无聊的序列.n<=2 ...

  7. [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)

    解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...

  8. Java中使用IO流实现大文件的分裂与合并

    文件分割应该算一个比较实用的功能,举例子说明吧比如说:你有一个3G的文件要从一台电脑Copy到另一台电脑, 但是你的存储设备(比如SD卡)只有1G ,这个时候就可以把这个文件切割成3个1G的文件 ,分 ...

  9. 模板——伸展树 splay 实现快速分裂合并的序列

    伸展操作:将treap中特定的结点旋转到根 //将序列中从左数第k个元素伸展到根,注意结点键值保存的是原序列id void splay(Node* &o, int k) { ] == NULL ...

随机推荐

  1. [java]反射1 2017-06-25 21:50 79人阅读 评论(10) 收藏

    很多东西的实现基础,都是反射,spring的AOP,动态代理等等,下面咱们来学习一下Java的反射 什么是反射? JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于 ...

  2. 洛谷 P3434 [POI2006]KRA-The Disks 贪心

    目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输出样例 输出样例 说明 思路 AC代码 题面 题目链接 P3434 [POI2006]KRA-The Disks 题目 ...

  3. Leetcode695.Max Area of Island岛屿的最大面积

    给定一个包含了一些 0 和 1的非空二维数组 grid , 一个 岛屿 是由四个方向 (水平或垂直) 的 1 (代表土地) 构成的组合.你可以假设二维矩阵的四个边缘都被水包围着. 找到给定的二维数组中 ...

  4. 一.JDBC学习入门

    一.JDBC相关概念介绍 1.1.数据库驱动 这里的驱动的概念和平时听到的那种驱动的概念是一样的,比如平时购买的声卡,网卡直接插到计算机上面是不能用的,必须要安装相应的驱动程序之后才能够使用声卡和网卡 ...

  5. li设置多选和取消选择的样式、输入数据类型判断

    li设置多选和取消选择的样式: $('li').click(function(){ if($(this).hasClass('active')) {$(this).removeClass('activ ...

  6. Vagrant-安装教程及常见问题

    http://ju.outofmemory.cn/entry/346215 前言: Vagrant是一个基于Ruby的工具,用于创建和部署虚拟化开发环境. 它的主要意义是让所有开发人员都使用和线上服务 ...

  7. ASO优化经验:APP关键字优化的技巧

    当开发首款产品的时候,可能你根本连ASO是什么都不知道,因为有太多别的事情需要你做.大多数新手开发商甚至到游戏要进入Appstore的时候才知道有“关键字”这件事要去研究.正因为这些开发商几乎没有在关 ...

  8. 2019-4-7-VisualStudio-解决方案筛选器-slnf-文件

    title author date CreateTime categories VisualStudio 解决方案筛选器 slnf 文件 lindexi 2019-04-07 11:34:59 +08 ...

  9. linux环境变量设置和默认执行语句设置

    环境变量设置 1.export export ORACLE_HOME=/usr/local/instantclient_12_2export PATH=$ORACLE_HOME:$PATHexport ...

  10. iOS-CoreLocation:无论你在哪里,我都要找到你!

    作者:@翁呀伟呀 授权本站转载 CoreLocation 1.定位 使用步骤: 创建CLLocationManager示例,并且需要强引用它 设置CLLocationManager的代理,监听并获取所 ...