题链:

Splay
很好的题,但是把智障的我给恶心到了。。。
 
首先不难发现,最后没有匹配的括号的样子一定是 ))))..((((...
即左边是右括号(设个数为nr),右边是做括号(设个数为nl)
则答案为 ⌈nl÷2⌉ + ⌈nr÷2⌉ (⌈ ⌉:向上取整)
 
若把 '(' 看成 1,把 ')' 看成 -1,
那么在这个只含有 1 和 -1 的序列里,
前缀最小值的相反数就等于nr,
后缀最大值的就等于nl
 
所以对于询问操作来说,在Splay中记录:
key[x](节点x是 1 还是 -1)
sum[x](x子树对应区间的sum和)
pmn[x](x子树对应区间的前缀最小值),
smx[x](x子树对应区间的后缀最大值)。
 
对于第二个反转操作
可以看出,只是把对应区间的 1→ -1,-1→ 1,
所以再多维护两个东西
pmx[x](x子树对应区间的前缀最大值),
smn[x](x子树对应区间的后缀最小值)。
然后把记录的 key[x],sum[x],pmn[x],pmx[x],smn[x],smx[x]全部取反(都乘上-1),
并且 swap(pmn[x],pmx[x]), swap(smn[x],smx[x])(因为取反了啊~)
再打个lazy标记,就好啦。
 
对于第三个翻转操作
就只需交换左右子树,
并且 swap(pmx[x],smx[x]),swap(pmn[x],smn[x]) (只是把序列反了起来,所以交换前后缀信息即可)
然后打一个lazy标记。
 
因为lazy标记不存在先后影响,所以lazy下放时随便先放哪个都可以的。
 
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 100500
using namespace std;
int N,M;
struct SPT{
int pmx[MAXN],pmn[MAXN],smx[MAXN],smn[MAXN],sum[MAXN],key[MAXN];
int ch[MAXN][2],siz[MAXN],fa[MAXN],lazy[MAXN],rt;
void Reverse(int x){
sum[x]*=-1; key[x]*=-1;
pmx[x]*=-1; pmn[x]*=-1; swap(pmx[x],pmn[x]);
smx[x]*=-1; smn[x]*=-1; swap(smx[x],smn[x]);
}
void Flip(int x){
swap(pmx[x],smx[x]);
swap(pmn[x],smn[x]);
swap(ch[x][0],ch[x][1]);
}
void Pushup(int x){
siz[x]=siz[ch[x][0]]+1+siz[ch[x][1]];
sum[x]=sum[ch[x][0]]+key[x]+sum[ch[x][1]];
pmx[x]=max(pmx[ch[x][0]],sum[ch[x][0]]+key[x]+pmx[ch[x][1]]);
pmn[x]=min(pmn[ch[x][0]],sum[ch[x][0]]+key[x]+pmn[ch[x][1]]);
smx[x]=max(smx[ch[x][1]],sum[ch[x][1]]+key[x]+smx[ch[x][0]]);
smn[x]=min(smn[ch[x][1]],sum[ch[x][1]]+key[x]+smn[ch[x][0]]);
}
void Pushdown(int x){
if(lazy[x]&1){
Reverse(ch[x][0]); lazy[ch[x][0]]^=1;
Reverse(ch[x][1]); lazy[ch[x][1]]^=1;
lazy[x]^=1;
}
if(lazy[x]&2){
Flip(ch[x][0]); lazy[ch[x][0]]^=2;
Flip(ch[x][1]); lazy[ch[x][1]]^=2;
lazy[x]^=2;
}
}
void Rotate(int x,int &k){
static int y,z,l,r;
y=fa[x]; z=fa[y];
l=ch[y][0]!=x; r=l^1;
if(!z) k=x;
else ch[z][ch[z][0]!=y]=x;
fa[ch[x][r]]=y; fa[y]=x; fa[x]=z;
ch[y][l]=ch[x][r]; ch[x][r]=y;
Pushup(y);
}
void Splay(int x,int &k){
static int y,z;
while(x!=k){
y=fa[x]; z=fa[y];
if(y!=k) (ch[z][0]!=y)^(ch[y][0]!=x)?
Rotate(x,k):Rotate(y,k);
Rotate(x,k);
}
Pushup(x);
}
int find(int x,int num){
if(lazy[x]) Pushdown(x);
if(num<=siz[ch[x][0]]) return find(ch[x][0],num);
else if(num==siz[ch[x][0]]+1) return x;
else return find(ch[x][1],num-siz[ch[x][0]]-1);
}
int Split(int l,int r){
static int dl,dr;
dl=find(rt,l); dr=find(rt,r+2);
Splay(dl,rt); Splay(dr,ch[dl][1]);
return ch[dr][0];
}
void Modify(int l,int r,int type){
static int p;
p=Split(l,r);
if(type==1) Reverse(p);
else Flip(p);
lazy[p]^=type;
Pushup(fa[p]); Pushup(fa[fa[p]]);
}
void Build(int &x,int dad,int l,int r){
static char c;
if(l>r) return;
x=(l+r)>>1; fa[x]=dad;
Build(ch[x][0],x,l,x-1);
scanf(" %c",&c); key[x]=(c=='('?1:-1);
Build(ch[x][1],x,x+1,r);
Pushup(x);
}
void BorderBuild(){
rt=N+1;
key[N+1]=0; key[N+2]=0;
ch[N+1][1]=N+2; fa[N+2]=N+1;
Build(ch[N+2][0],N+2,1,N);
Pushup(N+2); Pushup(N+1);
}
int Query(int l,int r){
static int p,ANS,nl,nr;
p=Split(l,r);
nl=-pmn[p]; nr=smx[p];
ANS=(nl+1)/2+(nr+1)/2;
return ANS;
}
}DT;
int main(){
freopen("/home/noilinux/Documents/模块学习/2209.in","r",stdin);
scanf("%d%d",&N,&M);
DT.BorderBuild();
for(int i=1,c,l,r;i<=M;i++){
scanf("%d%d%d",&c,&l,&r);
if(c==0) printf("%d\n",DT.Query(l,r));
else DT.Modify(l,r,c);
}
return 0;
}

  

 

●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]括号序列 平衡树

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

  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. BZOJ2209: [Jsoi2011]括号序列

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

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

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

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

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

  9. BZOJ2209 [Jsoi2011]括号序列 splay

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

随机推荐

  1. Beta阶段敏捷冲刺报告-DAY5

    Beta阶段敏捷冲刺报告-DAY5 Scrum Meeting 敏捷开发日期 2017.11.6 会议时间 12:00 会议地点 软工所 参会人员 全体成员 会议内容 乱序问题的解决,异常输入提示 讨 ...

  2. 20162328蔡文琛week06

    学号 2016-2017-2 <程序设计与数据结构>第X周学习总结 教材学习内容总结 继承是从已有类派生出一个新类的过程. 继承的目的之一之复用已有的软件. 继承呢在子类和父类见建立了is ...

  3. 团队作业7——第二次项目冲刺(Beta版本12.05-12.07)

    1.当天站立式会议照片 本次会议内容:1:每个人汇报自己完成的工作.2:组长分配各自要完成的任务. 2.每个人的工作 黄进勇:项目整合,后台代码. 李勇:前台界面优化. 何忠鹏:数据库模块. 郑希彬: ...

  4. 2017-2018-1 我爱学Java 第四五周 作业

    <打地鼠>Android游戏--需求规格说明书 工作流程 组员分工及工作量比例 <需求规格说明书>的码云链接 总结与反思 参考资料 工作流程 小组成员预先参考蓝墨云班课第八周中 ...

  5. sys模块的使用

    import sys,time ''' if sys.argv[1]=='sleepy': print('nongsi') else: print('....')''' #进度条 for i in r ...

  6. 树莓派3启动wifi并且配置wifi

    概述 树莓派3内置了wifi和蓝牙模块,我们不用像以前的版本那样,再去购买一个外接的模块练到raspberry上. 当我们第一次启动了树莓派的时候,必然使用了网线,但是之后的每一次使用,我们当然更希望 ...

  7. 第5章 子网划分和CIDR

    第5章 子网划分和CIDR 划分网络 根据A类.B类或C类网络ID来识别网段具有一些局限性,主要是在网络级别之下不能对地址空间进行任何逻辑细分 如果一个IP是一个A类网络.数据报到达网关,然后传输到9 ...

  8. aws - shadow 影子使用

    参考链接: https://github.com/aws/aws-iot-device-sdk-java 一.设备注册 二.设备主题

  9. Linux知识积累(3)$()和${}和$(())和(())

    $()和${}和$(())和(()) $()和${}的用法:在 bash shell 中,$( ) 与 ` ` (反引号) 都是用来做命令替换用(command substitution)的.而 $( ...

  10. 真正理解拉格朗日乘子法和 KKT 条件

        这篇博文中直观上讲解了拉格朗日乘子法和 KKT 条件,对偶问题等内容.     首先从无约束的优化问题讲起,一般就是要使一个表达式取到最小值: \[min \quad f(x)\]     如 ...