【bzoj2329】[HNOI2011]括号修复 Splay
题目描述
题解
Splay
由于有区间反转操作,因此考虑Splay。
考虑答案:缩完括号序列后剩下的一定是 $a$ 个')'+ $b$ 个'(',容易发现答案等于 $\lceil\frac a2\rceil+\lceil\frac b2\rceil$ 。
怎么维护:区间合并,对于每个节点维护子树缩完括号序列后')'和'('的数目,然后pushup时考虑缩括号序列的过程,相应调整即可。
由于有Invent操作,因此还需要维护反括号序列缩完之后')'和'('的数目,并维护相应标记。
由于有Swap操作,因此需要维护相应标记。需要注意的是:这里的Swap不是镜面反转,而是直接交换,换句话说就是翻转后括号方向不变。因此不能直接交换')'的数目和'('的数目,而是相当于交换后再Invent一次,即交换')'的数目和反括号序列'('的数目、交换'('的数目和反括号序列')'的数目。
由于有Replace操作,因此还需要维护区间染色标记。
时间复杂度 $O(n\log n)$
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
int fa[N] , c[2][N] , si[N] , w[N] , sum[N][2][2] , tag[N] , rev[N] , flip[N] , root;
char str[N];
inline void pushup(int x)
{
int l = c[0][x] , r = c[1][x];
si[x] = si[l] + si[r] + 1;
sum[x][0][0] = sum[l][0][0] + max(sum[r][0][0] - sum[l][0][1] + w[x] , 0);
sum[x][0][1] = sum[r][0][1] + max(sum[l][0][1] - sum[r][0][0] - w[x] , 0);
sum[x][1][0] = sum[l][1][0] + max(sum[r][1][0] - sum[l][1][1] - w[x] , 0);
sum[x][1][1] = sum[r][1][1] + max(sum[l][1][1] - sum[r][1][0] + w[x] , 0);
}
inline void pushdown(int x)
{
int l = c[0][x] , r = c[1][x];
if(rev[x])
{
w[l] = -w[l] , tag[l] = -tag[l] , swap(sum[l][0][0] , sum[l][1][0]) , swap(sum[l][0][1] , sum[l][1][1]) , rev[l] ^= 1;
w[r] = -w[r] , tag[r] = -tag[r] , swap(sum[r][0][0] , sum[r][1][0]) , swap(sum[r][0][1] , sum[r][1][1]) , rev[r] ^= 1;
rev[x] = 0;
}
if(flip[x])
{
swap(c[0][l] , c[1][l]) , swap(sum[l][0][0] , sum[l][1][1]) , swap(sum[l][0][1] , sum[l][1][0]) , flip[l] ^= 1;
swap(c[0][r] , c[1][r]) , swap(sum[r][0][0] , sum[r][1][1]) , swap(sum[r][0][1] , sum[r][1][0]) , flip[r] ^= 1;
flip[x] = 0;
}
if(tag[x])
{
w[l] = w[r] = tag[l] = tag[r] = tag[x];
if(tag[x] == 1)
{
sum[l][0][0] = sum[l][1][1] = si[l] , sum[l][0][1] = sum[l][1][0] = 0;
sum[r][0][0] = sum[r][1][1] = si[r] , sum[r][0][1] = sum[r][1][0] = 0;
}
else
{
sum[l][0][0] = sum[l][1][1] = 0 , sum[l][0][1] = sum[l][1][0] = si[l];
sum[r][0][0] = sum[r][1][1] = 0 , sum[r][0][1] = sum[r][1][0] = si[r];
}
tag[x] = 0;
}
}
int build(int l , int r)
{
if(l > r) return 0;
int mid = (l + r) >> 1;
c[0][mid] = build(l , mid - 1) , fa[c[0][mid]] = mid;
c[1][mid] = build(mid + 1 , r) , fa[c[1][mid]] = mid;
pushup(mid);
return mid;
}
inline void rotate(int &k , int x)
{
int y = fa[x] , z = fa[y] , l = (c[1][y] == x) , r = l ^ 1;
if(y == k) k = x;
else c[c[1][z] == y][z] = x;
fa[x] = z , fa[y] = x , fa[c[r][x]] = y , c[l][y] = c[r][x] , c[r][x] = y;
pushup(y) , pushup(x);
}
inline void splay(int &k , int x)
{
while(x != k)
{
int y = fa[x] , z = fa[y];
if(y != k)
{
if((c[0][y] == x) ^ (c[0][z] == y)) rotate(k , x);
else rotate(k , y);
}
rotate(k , x);
}
}
int find(int k , int x)
{
pushdown(k);
if(x <= si[c[0][k]]) return find(c[0][k] , x);
else if(x > si[c[0][k]] + 1) return find(c[1][k] , x - si[c[0][k]] - 1);
else return k;
}
int split(int l , int r)
{
int a = find(root , l) , b = find(root , r + 2);
splay(root , a) , splay(c[1][root] , b);
return c[0][c[1][root]];
}
int main()
{
int n , m , i , x , y , z;
scanf("%d%d%s" , &n , &m , str + 2);
for(i = 2 ; i <= n + 1 ; i ++ ) w[i] = (str[i] == ')' ? 1 : -1);
root = build(1 , n + 2);
while(m -- )
{
scanf("%s%d%d" , str , &x , &y) , z = split(x , y);
if(str[0] == 'R')
{
scanf("%s" , str);
if(str[0] == ')') sum[z][0][0] = sum[z][1][1] = si[z] , sum[z][0][1] = sum[z][1][0] = 0 , w[z] = tag[z] = 1;
else sum[z][0][0] = sum[z][1][1] = 0 , sum[z][0][1] = sum[z][1][0] = si[z] , w[z] = tag[z] = -1;
pushup(fa[z]) , pushup(root);
}
else if(str[0] == 'S') swap(c[0][z] , c[1][z]) , swap(sum[z][0][0] , sum[z][1][1]) , swap(sum[z][0][1] , sum[z][1][0]) , flip[z] ^= 1 , pushup(fa[z]) , pushup(root);
else if(str[0] == 'I') w[z] = -w[z] , tag[z] = -tag[z] , swap(sum[z][0][0] , sum[z][1][0]) , swap(sum[z][0][1] , sum[z][1][1]) , rev[z] ^= 1 , pushup(fa[z]) , pushup(root);
else printf("%d\n" , (sum[z][0][0] + 1) / 2 + (sum[z][0][1] + 1) / 2);
}
return 0;
}
【bzoj2329】[HNOI2011]括号修复 Splay的更多相关文章
- BZOJ2329 HNOI2011 括号修复 splay+贪心
找平衡树练习题的时候发现了这道神题,可以说这道题是近几年单考splay的巅峰之作了. 题目大意:给出括号序列,实现区间翻转,区间反转和区间更改.查询区间最少要用几次才能改成合法序列. 分析: 首先我们 ...
- BZOJ2329: [HNOI2011]括号修复(Splay)
解题思路: Replace.Swap.Invert都可以使用Splay完美解决(只需要解决一下标记冲突就好了). 最后只需要统计左右括号冲突就好了. 相当于动态统计最大前缀合和最小后缀和. 因为支持翻 ...
- BZOJ 2329: [HNOI2011]括号修复( splay )
把括号序列后一定是))))((((这种形式的..所以维护一个最大前缀和l, 最大后缀和r就可以了..答案就是(l+1)/2+(r+1)/2...用splay维护,O(NlogN). 其实还是挺好写的, ...
- bzoj千题计划222:bzoj2329: [HNOI2011]括号修复(fhq treap)
http://www.lydsy.com/JudgeOnline/problem.php?id=2329 需要改变的括号序列一定长这样 :)))((( 最少改变次数= 多余的‘)’/2 [上取整] + ...
- BZOJ 2329: [HNOI2011]括号修复 [splay 括号]
题目描述 一个合法的括号序列是这样定义的: 空串是合法的. 如果字符串 S 是合法的,则(S)也是合法的. 如果字符串 A 和 B 是合法的,则 AB 也是合法的. 现在给你一个长度为 N 的由‘(' ...
- BZOJ 2329/2209 [HNOI2011]括号修复 (splay)
题目大意: 让你维护一个括号序列,支持 1.区间修改为同一种括号 2.区间内所有括号都反转 3.翻转整个区间,括号的方向不变 4.查询把某段区间变为合法的括号序列,至少需要修改多少次括号 给跪了,足足 ...
- BZOJ2329 [HNOI2011]括号修复
把左括号看做$1$,右括号看做$-1$,于是查询操作等于查询一个区间左边右边最大(最小)子段和 支持区间翻转,反转,覆盖操作...注意如果有覆盖操作,之前的操作全部作废了...于是在下传标记的时候要最 ...
- 2019.03.25 bzoj2329: [HNOI2011]括号修复(fhq_treap)
传送门 题意简述: 给一个括号序列,要求支持: 区间覆盖 区间取负 区间翻转 查询把一个区间改成合法括号序列最少改几位 思路: 先考虑静态的时候如何维护答案. 显然把所有合法的都删掉之后序列长这样: ...
- 【BZOJ2329/2209】[HNOI2011]括号修复/[Jsoi2011]括号序列 Splay
[BZOJ2329/2209][HNOI2011]括号修复/[Jsoi2011]括号序列 题解:我们的Splay每个节点维护如下东西:左边有多少多余的右括号,右边有多少多余的左括号,同时为了反转操作, ...
随机推荐
- Linux 删除用户时报错:userdel: user zhoulijiang is currently used by process 1
一.发现问题: 有技术人员离职,需要删除系统帐号,但是进行删除操作的时候报:" userdel: user zhoulijiang is currently used by process ...
- Android 学习1
使用eclipse做为开发IDE, 导包快捷键 在显红的地方按shift+ctrl+o 另外自动补全使用alt+/
- python全栈开发-面向对象-进阶2
python_day_19 今日主要内容: 1.抽象类,接口类 2.多态 3.封装 1.抽象类,接口类 python 没有接口这个概念接口类,抽象类: 制定一个规范. 举个栗子:你的项目经理提一个需求 ...
- jenkins 入门教程
jenkins是一个广泛用于持续构建的可视化web工具,持续构建说得更直白点,就是各种项目的"自动化"编译.打包.分发部署.jenkins可以很好的支持各种语言(比如:java, ...
- Linux 安装ActiveMQ(使用Mac远程访问)
阅读本文需要安装JDK 一 ActiveMQ简介 activemq是用java语言编写的一款开源消息总线 activemq是apache出品 activemq消息的传递有两种类型 一种是点对点: 即一 ...
- Boss直聘邮件通知小脚本
Boss 基于Python3的找工作利器--Boss直聘来消息邮件通知, 自动发送简历脚本,O(∩_∩)O~ 无聊写的,因为有时候觉得找工作心急如焚,想自动回复自动发简历啊有木有~~~ github地 ...
- cmake-index-3.11.4机翻
index next | CMake » git-stage git-master latest release 3.13 3.12 3.11.4 3.10 3.9 3.8 3.7 3.6 3.5 3 ...
- [kuangbin带你飞]专题一 简单搜索 回顾总结
第二题:bfs,忘了将queue清空. 第三题:bfs,记得使用vis数组,防止重复入队
- Web安全入门书籍推荐
<Web应用安全权威指南> 链接:https://pan.baidu.com/s/1wZgv3c9jhWm1bAUHZw3gEg 提取码:teqj <黑客攻防技术宝典__Web实战篇 ...
- [转]如何设计自适应屏幕大小的网页 Responsive Web Design
随着3G的普及,越来越多的人使用手机上网. 移动设备正超过桌面设备,成为访问互联网的最常见终端.于是,网页设计师不得不面对一个难题:如何才能在不同大小的设备上呈现同样的网页? 手机的屏幕比较小,宽度通 ...