2209: [Jsoi2011]括号序列

Time Limit: 20 Sec  Memory Limit: 259 MB
Submit: 1404  Solved: 699
[Submit][Status][Discuss]

Description

Input

输入数据的第一行包含两个整数N和Q,分别表示括号序列的长度,以及操作的个数。
第二行包含一个长度为N的括号序列。
接下来Q行,每行三个整数t、x和y,分别表示操作的类型、操作的开始位置和操作的结
束位置,输入数据保证x不小于y。其中t=0表示询问操作、t=1表示反转操作、t=2表示翻转操
作。

Output

对于每一个询问操作,输出一行,表示将括号序列的该子序列修改为配对,所需的最少改动
个数。

Sample Input

6 3
)(())(
0 1 6
0 1 4
0 3 4

Sample Output

2
2
0

HINT

100%的数据满足N,Q不超过10^5

Source

第一轮

首先,对于一个括号序列,例如:())()(((,我们把可以匹配的去掉,就变成了:)(((。换句话说,对于一般的括号序列,化简以后就变成了左边x个")",右边y个"("。显然(x+y)为偶数,我们可以发现此时答案为x/2+y/2(x,y为偶数)或者x/2+1+y/2+1(x,y为奇数),合并一下就是[(x+1)/2]+[(y+1)/2]。

       关键是对于序列(l,r),x和y怎么求。实际上我们发现x就是求左端点为l,右端点<=r时,序列中右括号比左括号多的个数的最大值(>=0)。换句话说,如果令"("=1",("=-1,实际上x就是最小左子段和,y就是最大右子段和。由于还有反转(不是翻转)操作,因此还需要维护最大左子段和和最小右子段和。为了维护最小最大子段和,还需要维护一个区间和。
      然后就可以用splay的经典提取操作了。打两个标记就好了。
 
因为在find的过程中已经翻转保证了当前根那部分是正确就可以了。
 #pragma GCC optimize(2)
#pragma G++ optimize(2)
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring> #define N 100007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-;ch=getchar();}
while(isdigit(ch)){x=(x<<)+(x<<)+ch-'';ch=getchar();}
return x*f;
} int n,m,rt;
int c[N][],sum[N],a[N],sz[N],fa[N];
bool rev[N],ops[N];
char ch[N];
struct Node
{
int l0,l1,r0,r1;
void LDI()
{
l0=-l0,l1=-l1;
r0=-r0,r1=-r1;
}
}val[N]; void update(int p)
{
int l=c[p][],r=c[p][];
sum[p]=a[p]+sum[l]+sum[r],sz[p]=sz[l]+sz[r]+;
val[p].l0=min(val[l].l0,sum[l]+a[p]+val[r].l0);
val[p].l1=max(val[l].l1,sum[l]+a[p]+val[r].l1);
val[p].r0=min(val[r].r0,sum[r]+a[p]+val[l].r0);
val[p].r1=max(val[r].r1,sum[r]+a[p]+val[l].r1);
}
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y],l,r;
if(c[y][]==x)l=;else l=;r=l^;
if(y==k)k=x;
else if(c[z][]==y)c[z][]=x;
else c[z][]=x;
fa[x]=z,fa[y]=x,fa[c[x][r]]=y;
c[y][l]=c[x][r],c[x][r]=y;
update(y),update(x);
}
void splay(int x,int &k)
{
while(x!=k)
{
int y=fa[x],z=fa[y];
if(y!=k)
{
if(c[y][]==x^c[z][]==y) rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
void build(int &p,int l,int r,int par)
{
if(l>r){p=;return;}
p=(l+r)>>;fa[p]=par;
if(l==r)
{
sum[p]=a[l],sz[p]=;
if(a[l]<) val[p].l0=val[p].r0=-;
else val[p].l1=val[p].r1=;
return;
}
build(c[p][],l,p-,p),build(c[p][],p+,r,p);
update(p);
}
void rollback(int p)
{
ops[p]^=,sum[p]=-sum[p],a[p]=-a[p];
swap(val[p].l0,val[p].l1),swap(val[p].r0,val[p].r1);
val[p].LDI();
}
void rever(int p)
{
rev[p]^=;
swap(val[p].l0,val[p].r0);
swap(val[p].l1,val[p].r1);
}
void pushdown(int p)
{
if (rev[p])
{
swap(c[p][],c[p][]); rev[p]^=;
rever(c[p][]),rever(c[p][]);
}
if (ops[p])
{
rollback(c[p][]),rollback(c[p][]); ops[p]^=;
}
}
int find(int p,int x)
{
pushdown(p);
int l=c[p][],r=c[p][];
if(sz[l]+==x)return p;
else if(sz[l]>=x) return find(l,x);else return find(r,x-sz[l]-);
}
int main()
{
n=read(),m=read();
scanf("%s",ch+);
for (int i=;i<=n+;i++)
if(ch[i]=='(')a[i]=;else a[i]=-;
build(rt,,n+,);
while(m--)
{
int t=read(),l=read(),r=read();
l=find(rt,l),r=find(rt,r+);
splay(l,rt),splay(r,c[rt][]);
int p=c[r][];
if(!t)printf("%d\n",(val[p].r1+)/-(val[p].l0-)/);//左边取相反数.
else if (t==) rollback(p); else rever(p);
}
}

bzoj 2209 [Jsoi2011]括号序列 平衡树的更多相关文章

  1. bzoj 2209: [Jsoi2011]括号序列 splay

    2209: [Jsoi2011]括号序列 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 833  Solved: 392[Submit][Status ...

  2. BZOJ 2209: [Jsoi2011]括号序列 [splay 括号]

    2209: [Jsoi2011]括号序列 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1111  Solved: 541[Submit][Statu ...

  3. ●BZOJ 2209 [Jsoi2011]括号序列

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2209 题解: Splay 很好的题,但是把智障的我给恶心到了...   首先不难发现,最后没 ...

  4. 【BZOJ】2209: [Jsoi2011]括号序列(splay)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2209 splay又犯逗........upd1那里的sum忘记赋值反............. 本题 ...

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

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

  6. [HNOI2011]括号修复 / [JSOI2011]括号序列

    传送门 Solution 一道题花费了两天的时间-- 在大佬@PinkRabbit的帮助下,终于AC了,感动-- 首先,我们考虑一个括号序列被修改成合法序列需要的次数: 我们需要修改的其实是形如... ...

  7. 洛谷 P3215 [HNOI2011]括号修复 / [JSOI2011]括号序列(fhq-treap)

    题目链接 题意:有一个长度为 \(n\) 的括号序列,你需要支持以下操作: 将 \([l,r]\) 中所有括号变为 \(c\) 将 \([l,r]\) 区间翻转 将 \([l,r]\) 区间中左括号变 ...

  8. BZOJ2209: [Jsoi2011]括号序列

    传送门 splay练习. 考虑把括号序列转化成类似于区间最大/最小值的情况. 显然我们可以知道括号序列消完的情况肯定是$a$个)和$b$个(,那么把这些括号全部合法化的代价显然就是$\frac{a+1 ...

  9. BZOJ2209 [Jsoi2011]括号序列 splay

    原文链接http://www.cnblogs.com/zhouzhendong/p/8093556.html 题目传送门 - BZOJ2209 题解 我太弱了,调出这题感觉都要吐了. 题解懒得写了. ...

随机推荐

  1. Oracle内连接、外连接、右外连接、全外连接小总结

    数据库版本:Oracle 9i 表TESTA,TESTB,TESTC,各有A, B两列 A B 001 10A 002 20A A B 001 10B 003 30B A B 001 10C 004 ...

  2. Excel的列编号 例如:A对应1,Z对应26,AA对应27,AZ对应52的JavaScript怎么写?

    今天碰到的题目,当时不会.回来想了一会,调试了一下,然后想上网对答案,发现竟然没有!!! function str(num){ if(num<=0){ alert("excel表格貌似 ...

  3. ASP.NET导出word实例

    ASP.NET导出word实例 最近遇到一个题目就是如何在asp.net中将数据导出到word中,由于数据是动态的,所以需要在后台拼出想要的的格式,翻遍了网页找出了一个比较满意的代码,感谢那位高手.代 ...

  4. myeclipse取消js校验

    最近玩一个新的项目,项目里面集成了别的项目,在从SVN上第一次荡下来的时候编译的时候老是校验jq文件,老是被卡主,设置myeclipse环境的时候我已经取消了所有的js校验了,但是还是不行.恼火之余, ...

  5. Android开发之蓝牙Socket

    蓝牙Server端就是通过线程来注册一个具有名称和唯一识别的UUID号的BluetoothServerSocket, 然后就一直监听Client端(BluetoothSocket)的请求,并对这些请求 ...

  6. Activity的setContentView的流程

    最简单的Activity中的内容大致是这样的: public class MainActivity extends Activity { @Override public void onCreate( ...

  7. Asp.net Core 入门实战 2.请求流程

    Asp.Net Core 是开源,跨平台,模块化,快速而简单的Web框架. Asp.net Core官网的一个源码合集,方便一次性Clone,喜欢的(Star),本系列持续更新,也可以通过我的网站访问 ...

  8. Mac 提示安装包已损坏

    mac 系统更新到 Sierra 10.12.X 版本后,从非 itunes 渠道下载的软件安装时都会报 “安装包已损坏” 的错误,这是新的系统设置的安全机制,为了解决这个问题,可以在命令行中输入命令 ...

  9. 图说:为什么Java中的字符串被定义为不可变的

    8张图,看懂Java字符串的不变性 字符串,想必大家最熟悉不过了,通常我们在代码中有几种方式可以创建字符串,比如:String s = "Hollis";这时,其实会在堆内存中创建 ...

  10. 简易发号SQL,可用于生成指定前缀自增序列,如订单号,生成优惠券码等

    需求1:订单号要求唯一.长度不太长.自增.但不能通过早上订单号和晚上订单号相减推算出平台大概一天的单量 需求2:要求生成10w张优惠券,要求券码唯一.不能太长,不能轻易猜测出其他券码 根据这些需求提供 ...