【BZOJ2329】括号修复(Splay)

题面

BZOJ

洛谷

题解

本来想着用线段树来写

但是有一个区间翻转

所以不能用线段树了,就只能用平衡树

然后直接\(Splay\)就好了

注意一下几个标记的下放问题

这种数据结构真的没有什么思路可言。。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 111111
#define ls (t[x].ch[0])
#define rs (t[x].ch[1])
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Node
{
int ch[2],ff,size;
int lm,rm,lg,rg,sum,v;
int rev,eql,inv;
}t[MAX];
int rt;
void pushup(int x)
{
t[x].lm=max(t[ls].lm,t[ls].sum+t[x].v+t[rs].lm);
t[x].rm=max(t[rs].rm,t[rs].sum+t[x].v+t[ls].rm);
t[x].lg=min(t[ls].lg,t[ls].sum+t[x].v+t[rs].lg);
t[x].rg=min(t[rs].rg,t[rs].sum+t[x].v+t[ls].rg);
t[x].sum=t[ls].sum+t[rs].sum+t[x].v;
t[x].size=t[ls].size+t[rs].size+1;
}
void rotate(int x)
{
int y=t[x].ff,z=t[y].ff;
int k=t[y].ch[1]==x;
if(z)t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y;t[y].ff=x;
pushup(y);
}
void putrev(int x)
{
if(!x)return;
swap(t[x].lg,t[x].rg);
swap(t[x].lm,t[x].rm);
swap(ls,rs);t[x].rev^=1;
}
void putinv(int x)
{
if(!x)return;
t[x].v*=-1;t[x].inv^=1;t[x].sum*=-1;
swap(t[x].lm,t[x].lg);swap(t[x].rm,t[x].rg);
t[x].lm*=-1;t[x].lg*=-1;t[x].rm*=-1;t[x].rg*=-1;
}
void puteql(int x,int w)
{
if(!x)return;
t[x].eql=t[x].v=w;t[x].sum=t[x].size*w;
t[x].rev=t[x].inv=0;
t[x].lm=t[x].rm=max(0,t[x].sum);
t[x].lg=t[x].rg=min(0,t[x].sum);
}
void pushdown(int x)
{
if(t[x].eql)puteql(ls,t[x].eql),puteql(rs,t[x].eql),t[x].eql=0;
if(t[x].rev)putrev(ls),putrev(rs),t[x].rev^=1;
if(t[x].inv)putinv(ls),putinv(rs),t[x].inv^=1;
}
void Splay(int x,int goal)
{
while(t[x].ff!=goal)
{
int y=t[x].ff,z=t[y].ff;
if(z!=goal)
(t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
rotate(x);
}
if(!goal)rt=x;pushup(x);
}
int Kth(int x,int k)
{
while(233)
{
pushdown(x);
if(k<=t[ls].size)x=ls;
else if(k==t[ls].size+1)return x;
else k-=t[ls].size+1,x=rs;
}
}
int split(int l,int r)
{
int x=Kth(rt,l);Splay(x,0);
int y=Kth(rt,r+2);Splay(y,x);
return t[y].ch[0];
}
void Build(int l,int r,int ff)
{
if(l>r)return;
int mid=(l+r)>>1;
t[mid].ff=ff;
if(ff)t[ff].ch[ff<mid]=mid;
else rt=mid;
Build(l,mid-1,mid);Build(mid+1,r,mid);
pushup(mid);
}
char S[MAX];
int n,m;
int main()
{
n=read();m=read();
scanf("%s",S+1);
for(int i=1;i<=n;++i)t[i+1].v=(S[i]=='('?-1:1);
Build(1,n+2,0);
char ch[10];
while(m--)
{
scanf("%s",ch);
int l=read(),r=read(),x=split(l,r);
if(ch[0]=='Q')printf("%d\n",(t[x].lm+1)/2+(1-t[x].rg)/2);
else if(ch[0]=='S')putrev(x);
else if(ch[0]=='R')
{
scanf("%s",ch);int w=(ch[0]=='('?-1:1);
puteql(x,w);
}
else putinv(x);
}
return 0;
}

【BZOJ2329】括号修复(Splay)的更多相关文章

  1. BZOJ 2329: [HNOI2011]括号修复( splay )

    把括号序列后一定是))))((((这种形式的..所以维护一个最大前缀和l, 最大后缀和r就可以了..答案就是(l+1)/2+(r+1)/2...用splay维护,O(NlogN). 其实还是挺好写的, ...

  2. BZOJ2329 HNOI2011 括号修复 splay+贪心

    找平衡树练习题的时候发现了这道神题,可以说这道题是近几年单考splay的巅峰之作了. 题目大意:给出括号序列,实现区间翻转,区间反转和区间更改.查询区间最少要用几次才能改成合法序列. 分析: 首先我们 ...

  3. 【bzoj2329】[HNOI2011]括号修复 Splay

    题目描述 题解 Splay 由于有区间反转操作,因此考虑Splay. 考虑答案:缩完括号序列后剩下的一定是 $a$ 个')'+ $b$ 个'(',容易发现答案等于 $\lceil\frac a2\rc ...

  4. BZOJ2329: [HNOI2011]括号修复(Splay)

    解题思路: Replace.Swap.Invert都可以使用Splay完美解决(只需要解决一下标记冲突就好了). 最后只需要统计左右括号冲突就好了. 相当于动态统计最大前缀合和最小后缀和. 因为支持翻 ...

  5. BZOJ 2329: [HNOI2011]括号修复 [splay 括号]

    题目描述 一个合法的括号序列是这样定义的: 空串是合法的. 如果字符串 S 是合法的,则(S)也是合法的. 如果字符串 A 和 B 是合法的,则 AB 也是合法的. 现在给你一个长度为 N 的由‘(' ...

  6. [HNOI2011][bzoj 2329] 括号修复 [splay+前缀和]

    题面: http://www.lydsy.com/JudgeOnline/problem.php?id=2329 思路: 显然,操作4中输出补全的最小费用是关键 这决定了我们不可能在splay上只维护 ...

  7. BZOJ 2329/2209 [HNOI2011]括号修复 (splay)

    题目大意: 让你维护一个括号序列,支持 1.区间修改为同一种括号 2.区间内所有括号都反转 3.翻转整个区间,括号的方向不变 4.查询把某段区间变为合法的括号序列,至少需要修改多少次括号 给跪了,足足 ...

  8. 【BZOJ2329/2209】[HNOI2011]括号修复/[Jsoi2011]括号序列 Splay

    [BZOJ2329/2209][HNOI2011]括号修复/[Jsoi2011]括号序列 题解:我们的Splay每个节点维护如下东西:左边有多少多余的右括号,右边有多少多余的左括号,同时为了反转操作, ...

  9. 【BZOJ-2329&2209】括号修复&括号序列 Splay

    2329: [HNOI2011]括号修复 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 1007  Solved: 476[Submit][Statu ...

随机推荐

  1. 【redis的搭建】centos6.4下搭建redis

    说明:本文内容参考自一些资料,如有雷同,还请见谅. 部分参考: http://blog.csdn.net/su377486/article/details/51803616 http://blog.c ...

  2. 随身Wifi+win7 搭建http代理 域名劫持 抓包 内容篡改实验环境

    需求来源: 1.平板或手机是个封闭系统无法给wifi设置代理 2.需要利用filllder进行抓包,内容篡改等实验 拥有硬件资源:PC机器 + 小米随身wifi 方案1: NtBind Dns + N ...

  3. leetcode-优美的排列

    假设有从 1 到 N 的 N 个整数,如果从这 N 个数字中成功构造出一个数组,使得数组的第 i 位 (1 <= i <= N) 满足如下两个条件中的一个,我们就称这个数组为一个优美的排列 ...

  4. SQL Server变量杂谈

    学习SQL的过程有进步的话还是一件很美妙的事情的 在第一家公司虽然只呆了两年,但是感觉是我进步最快的两年.那时候工作和生活都挺充实的,每天都有一点点的收获和付出,其中最大的收获莫过于掌握一些核心技能. ...

  5. 如何停止AAD服务

    Connect-MsolService (Get-MSOLCompanyInformation).DirectorySynchronizationEnabled 用这个命令查看是enable还是Dis ...

  6. 从零开始的Python学习Episode 11——装饰器

    装饰器 装饰器是用来处理其他函数的函数,主要作用是在不修改原有函数的情况下添加新的功能,装饰器的返回值也是一个函数对象. 简单的装饰器 import time def show_time(f): de ...

  7. Kafka安装之三 spring-kafka实践

    一.spring-kafka配置详解 1.1 要是用spring-kafka 我们首先要在pom要.xml中引入spring-kafka包 <dependencies> <depen ...

  8. gevent协程、select IO多路复用、socketserver模块 改造多用户FTP程序例子

    原多线程版FTP程序:http://www.cnblogs.com/linzetong/p/8290378.html 只需要在原来的代码基础上稍作修改: 一.gevent协程版本 1. 导入geven ...

  9. [T-ARA][HUE]

    歌词来源:http://music.163.com/#/song?id=22704406 wa du seu mo geum to yo do ga tae 어딜가도 스페셜한게 없어 [eo-dil ...

  10. python mongodb操作大全

    数据库 增 use db1 #有则切换,无则新增 查 show dbs #查看所有 db #当前 删 db.dropDatabase() 集合: 增: db.user db.user.info db. ...