题目描述

一个合法的括号序列是这样定义的:

  1. 空串是合法的。

  2. 如果字符串 S 是合法的,则(S)也是合法的。

  3. 如果字符串 A 和 B 是合法的,则 AB 也是合法的。

现在给你一个长度为 N 的由‘('和‘)'组成的字符串,位置标号从 1 到 N。对这个字符串有下列四种操作:

  1. Replace a b c:将[a,b]之间的所有括号改成 c。例如:假设原来的字符串为:))())())(,那么执行操作 Replace 2 7 ( 后原来的字符串变为:)(((((()(。

  2. Swap a b:将[a,b]之间的字符串翻转。例如:假设原来的字符串为:))())())(,那么执行操作 Swap 3 5 后原来的字符串变为:))))(())(。

  3. Invert a b:将[a,b]之间的‘(’变成‘)’,‘)’变成‘(’。例如:假设原来的字符串为:))())())(,那么执行操作 Invert 4 8 后原来的字符串变为:))((()(((。

  4. Query a b:询问[a,b]之间的字符串至少要改变多少位才能变成合法的括号序列。改变某位是指将该位的‘(’变成‘)’或‘)’变成‘(’。注意执行操作 Query 并不改变当前的括号序列。例如:假设原来的字符串为:))())())(,那么执行操作 Query 3 6

的结果为 2,因为要将位置 5 的‘)’变成‘(’并将位置 6 的‘(’变成‘)’。

输入输出格式

输入格式:

从文件input.txt中读入数据,输入文件的第一行是用空格隔开的两个正整数N和M,分别表示字符串的长度和将执行的操作个数。第二行是长度为N的初始字符串S。接下来的M行是将依次执行的M个操作,其中操作名与操作数之间以及相邻操作数之间均用空格隔开。30%的数据满足

N,M≤3000。100%的数据满足N,M≤100000。

输出格式:

输出文件 output.txt 包含 T 行,其中 T 是输入的将执行的 M 个操作中 Query 操作出现的次数。Query 操作的每次出现依次对应输出文件中的一行,该行只有一个非负整数,表示执行对应 Query 操作的结果,即:所指字符串至少要改变多少位才能变成合法的括号序列。输入数据

保证问题有解。

输入输出样例

输入样例#1:

4 5
((((
Replace 1 2 )
Query 1 2
Swap 2 3
Invert 3 4
Query 1 4
输出样例#1:

1
2

说明

样例解释:输入中有2个Query操作,所以输出有2行。执行第一个Query操作时的括号序列为))((,因改变第1位可使[1,2]之间的字符串变成合法的括号序列,故输出的第一行为1。执行第二个Query操作时的括号序列为)((),因要改变第1位和第2位才能使[1,4]之间的字符串变成合法的括号序列,故输出的第二行为2。


去luogu偷题面


多了区间修改操作..................

区间修改后要把反转翻转标记清空

反转标记需要反转修改标记

PS:luogu时限不科学,要强开O2才过

#pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
#define lc t[x].ch[0]
#define rc t[x].ch[1]
#define pa t[x].fa
const int N=1e5+,INF=1e9;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x*f;
}
int n,Q,l,r,a[N];
char s[N],op[];
struct node{
int ch[],fa,size,v,sum,lmx,lmn,rmx,rmn,rev,flp,tag;
node():fa(){ch[]=ch[]=;}
}t[N];
int root;
inline int wh(int x){return t[pa].ch[]==x;}
inline void update(int x){
if(!x) return;
t[x].size=t[lc].size+t[rc].size+;
t[x].sum=t[lc].sum+t[rc].sum+t[x].v;
t[x].lmx=max(t[lc].lmx,max(t[lc].sum+t[x].v,t[lc].sum+t[x].v+t[rc].lmx));
t[x].lmn=min(t[lc].lmn,min(t[lc].sum+t[x].v,t[lc].sum+t[x].v+t[rc].lmn));
t[x].rmx=max(t[rc].rmx,max(t[rc].sum+t[x].v,t[rc].sum+t[x].v+t[lc].rmx));
t[x].rmn=min(t[rc].rmn,min(t[rc].sum+t[x].v,t[rc].sum+t[x].v+t[lc].rmn));
}
inline void rever(int x){
t[x].rev^=;
swap(lc,rc);
swap(t[x].lmx,t[x].rmx);
swap(t[x].lmn,t[x].rmn);
}
inline void flip(int x){
t[x].flp^=;
t[x].sum=-t[x].sum;t[x].v=-t[x].v;
t[x].lmx=-t[x].lmx;t[x].lmn=-t[x].lmn;
swap(t[x].lmx,t[x].lmn);
t[x].rmx=-t[x].rmx;t[x].rmn=-t[x].rmn;
swap(t[x].rmx,t[x].rmn);
t[x].tag=-t[x].tag;
}
inline void paint(int x,int d){
t[x].rev=t[x].flp=;
t[x].v=t[x].tag=d;t[x].sum=t[x].size*d;
t[x].lmx=t[x].rmx=max(d,t[x].sum);
t[x].lmn=t[x].rmn=min(d,t[x].sum);
}
inline void pushDown(int x){
if(t[x].rev){
if(lc) rever(lc);
if(rc) rever(rc);
t[x].rev=;
}
if(t[x].flp){
if(lc) flip(lc);
if(rc) flip(rc);
t[x].flp=;
}
if(t[x].tag){
if(lc) paint(lc,t[x].tag);
if(rc) paint(rc,t[x].tag);
t[x].tag=;
}
} inline void rotate(int x){
int f=t[x].fa,g=t[f].fa,c=wh(x);
if(g) t[g].ch[wh(f)]=x;t[x].fa=g;
t[f].ch[c]=t[x].ch[c^];t[t[f].ch[c]].fa=f;
t[x].ch[c^]=f;t[f].fa=x;
update(f);update(x);
}
inline void splay(int x,int tar){
for(;pa!=tar;rotate(x))
if(t[pa].fa!=tar) rotate(wh(x)==wh(pa)?pa:x);
if(tar==) root=x;
} int build(int l,int r,int f){//printf("build %d %d %d\n",l,r,f);
if(l>r) return ;
int x=(l+r)>>;
lc=build(l,x-,x);rc=build(x+,r,x);
t[x].fa=f;
t[x].rev=t[x].flp=t[x].tag=;
t[x].v=a[x];//not need
update(x);//printf("get %d %d %d %d %d %d %d %d %d\n",x,l,r,t[x].v,t[x].sum,t[x].lmx,t[x].lmn,t[x].rmx,t[x].rmn);
return x;
}
inline int kth(int k){//printf("kth %d\n",k);
int x=root,ls=;
while(x){
pushDown(x);
int _=ls+t[lc].size;//printf("size %d %d\n",x,_);
if(_<k&&k<=_+) return x;
else if(k<=_) x=lc;
else ls=_+,x=rc;
}
return ;
}
void Query(int l,int r){//printf("query %d %d\n",l,r);
int f=kth(l);splay(f,);
int x=kth(r+);splay(x,f);
int a=t[lc].lmx,b=t[lc].rmn;//printf("hi %d %d %d %d %d\n",f,x,lc,a,b);
printf("%d\n",(a+)/+(-b+)/);
}
void Flip(int l,int r){
int f=kth(l);splay(f,);
int x=kth(r+);splay(x,f);
flip(lc);update(x);update(f);
}
void Rever(int l,int r){
int f=kth(l);splay(f,);
int x=kth(r+);splay(x,f);
rever(lc);update(x);update(f);
}
void Cover(int l,int r){
char c[];scanf("%s",c);
int d= c[]=='('?-:;
int f=kth(l);splay(f,);
int x=kth(r+);splay(x,f);
paint(lc,d);update(x);update(f);
}
void print(int x){
pushDown(x);
if(lc) print(lc);
printf("%c ",t[x].v==-?'(':')');
if(rc) print(rc);
}
int main(){
//freopen("in.txt","r",stdin);
n=read();Q=read();
scanf("%s",s+);
for(int i=;i<=n;i++) a[i+]=s[i]=='('?-:;
//for(int i=1;i<=n+2;i++) printf("%d ",a[i]);puts("");
t[].lmn=t[].rmn=INF;
t[].lmx=t[].rmx=-INF;
root=build(,n+,root);
while(Q--){//print(root);puts(" end");
scanf("%s",op);l=read();r=read();
if(op[]=='R') Cover(l,r);
if(op[]=='S') Rever(l,r);
if(op[]=='I') Flip(l,r);
if(op[]=='Q') Query(l,r);
}
}

BZOJ 2329: [HNOI2011]括号修复 [splay 括号]的更多相关文章

  1. ●BZOJ 2329 [HNOI2011]括号修复.cpp

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=2329 题解: Splay 类似 BZOJ 2329 [HNOI2011]括号修复 只是多了一 ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. JAVA爬虫实践(实践四:webMagic和phantomjs和淘宝爬虫)

    webMagic虽然方便,但是也有它不适用的地方,比如定向的某个单页面爬虫,或者存在大量ajax请求,页面的跳转请求全都混淆在js里. 这时可以用webMagic结合phantomjs来真实模拟页面请 ...

  2. [高并发]抢红包设计(使用redis)

    假设一个需求,在某个预告活动中准备了10w个红包,100w人在某个时间点去开抢,每人只能抢1次,如何保证性能和准确性,下面我给出我的一个设计方案,抛砖引玉 分析瓶颈 查询用户是否已参与过活动 获取一个 ...

  3. SSH会话连接超时问题

    目前大多数ssh服务是运行在Linux系统上的sshd服务.当访问终端在windows上时,各终端软件,如,putty,SecureCRT等,大多支持设置向服务器端自动发送消息,来防止终端定期超时.其 ...

  4. vi命令加行号查找替换等命令

    一.加行号           : set nu二.vi查找:    当你用vi打开一个文件后,因为文件太长,如何才能找到你所要查找的关键字呢?在vi里可没有菜单-〉查找,              ...

  5. SpringMVC图片上传与显示

    @RestController @Scope("prototype") @RequestMapping("/xxxx/xxx/main") public cla ...

  6. Java泛型解析

    1. 概述    在引入范型之前,Java类型分为原始类型.复杂类型,其中复杂类型分为数组和类.引入范型后,一个复杂类型就可以在细分成更多的类型. 例如原先的类型List,现在在细分成List< ...

  7. Java数据持久层框架 MyBatis之API学习三(XML 映射配置文件)

    对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...

  8. JavaScript对象的valueOf()方法

    js对象中的valueOf()方法和toString()方法非常类似,但是,当需要返回对象的原始值而非字符串的时候才调用它,尤其是转换为数字的时候.如果在需要使用原始值的上下文中使用了对象,JavaS ...

  9. java面向对象的三大特性——继承

    ul,ol { margin: 0; list-style: none; padding: 0 } a { text-decoration: none; color: inherit } * { ma ...

  10. synchronized内存可见性理解

    一.背景 最近在看<Java并发编程实战>这本书,看到共享变量的可见性,其中说到"加锁的含义不仅仅局限于互斥行为,还包括内存可见性". 我对于内存可见性第一反应是vol ...