【BZOJ-2329】[HNOI2011] 括号修复
2018-02-26 20:32
369 查看
题目链接
Replace a b c:将[a,b]之间的所有括号改成 c。例如:假设原来的字符串为:))())())(,那么执行操作 Replace 2 7 ( 后原来的字符串变为:)(((((()(。
Swap a b:将[a,b]之间的字符串翻转。例如:假设原来的字符串为:))())())(,那么执行操作 Swap 3 5 后原来的字符串变为:))))(())(。
Invert a b:将[a,b]之间的‘(’变成‘)’,‘)’变成‘(’。例如:假设原来的字符串为:))())())(,那么执行操作 Invert 4 8 后原来的字符串变为:))((()(((。
Query a b:询问[a,b]之间的字符串至少要改变多少位才能变成合法的括号序列。改变某位是指将该位的‘(’变成‘)’或‘)’变成‘(’。
(合法就是符合日常书写)
先来研究一下对于n个” )” ,和m个 “(” 的最小修改次数
首先(m+n) 必为偶数,手玩可以发现:
ans=(n+1)/2+(m+1)/2ans=(n+1)/2+(m+1)/2
那么关键在于维护一个区间内的画简后的左右括号数。
既然左右要互相抵消,不妨我们设”(“为1,”)”为-1。
对于括号序列 ())()((())
假设我们从左到右,依次记录sum,那么就是:
1 0 -1 0 -1 0 1 2 1 0
发现最后左括号数是最小前缀的绝对值?
再从右到左:
-1 -2 -1 0 1 0 1 -1 -2 -1
发现右括号数是最大后缀?
(众人:好像是这么回事(雾))
于是就显然是这样了,维护最小前缀和最大后缀。
但是由于翻转操作的存在,似乎还要记录最小后缀和最大前缀,这样翻转时swap一下就行了 OVO
Splay搞起来就好了。
邻外这里操作较多,建议都写一个函数,方便pushdown()pushdown()(自己想想下放顺序)
代码如下(全写的指针···):
题目描述
现在给你一个长度为 N 的由‘(‘和‘)’组成的字符串,位置标号从 1 到 N。对这个字符串有下列四种操作:Replace a b c:将[a,b]之间的所有括号改成 c。例如:假设原来的字符串为:))())())(,那么执行操作 Replace 2 7 ( 后原来的字符串变为:)(((((()(。
Swap a b:将[a,b]之间的字符串翻转。例如:假设原来的字符串为:))())())(,那么执行操作 Swap 3 5 后原来的字符串变为:))))(())(。
Invert a b:将[a,b]之间的‘(’变成‘)’,‘)’变成‘(’。例如:假设原来的字符串为:))())())(,那么执行操作 Invert 4 8 后原来的字符串变为:))((()(((。
Query a b:询问[a,b]之间的字符串至少要改变多少位才能变成合法的括号序列。改变某位是指将该位的‘(’变成‘)’或‘)’变成‘(’。
(合法就是符合日常书写)
题解
首先一个括号序列如 ())()((()) ,中间已经抵消的可以去掉,变成: )(先来研究一下对于n个” )” ,和m个 “(” 的最小修改次数
首先(m+n) 必为偶数,手玩可以发现:
ans=(n+1)/2+(m+1)/2ans=(n+1)/2+(m+1)/2
那么关键在于维护一个区间内的画简后的左右括号数。
既然左右要互相抵消,不妨我们设”(“为1,”)”为-1。
对于括号序列 ())()((())
假设我们从左到右,依次记录sum,那么就是:
1 0 -1 0 -1 0 1 2 1 0
发现最后左括号数是最小前缀的绝对值?
再从右到左:
-1 -2 -1 0 1 0 1 -1 -2 -1
发现右括号数是最大后缀?
(众人:好像是这么回事(雾))
于是就显然是这样了,维护最小前缀和最大后缀。
但是由于翻转操作的存在,似乎还要记录最小后缀和最大前缀,这样翻转时swap一下就行了 OVO
Splay搞起来就好了。
邻外这里操作较多,建议都写一个函数,方便pushdown()pushdown()(自己想想下放顺序)
代码如下(全写的指针···):
#include<iostream> #include<cmath> #include<cstdio> #include<algorithm> #include<cstdlib> #include<cstring> using namespace std; inline int read() { int x=0;char ch=getchar();int t=1; for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') t=-1; for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch-48); return x*t; } #define ls son[0] #define rs son[1] #define __ NULL #define get_size(a) (a==__? 0:a->size) #define get_son(a) (a->fa->rs==a) #define get_min_l(a) (a==__? 0:a->min_l) #define get_max_r(a) (a==__? 0:a->max_r) #define get_min_r(a) (a==__? 0:a->min_r) #define get_max_l(a) (a==__? 0:a->max_l) #define get_sum(a) (a==__? 0:a->sum) struct node{ int size;int x; int min_l,max_r,sum; int max_l,min_r; int rp;bool sp; bool ip; node* fa;node* son[2]; node(){size=1;x=min_l=max_r=sum=0;fa=ls=rs=__;rp=sp=ip=0;max_l=min_r=0;} }*rt; int n,m; const int N=1e5+100; int opp ; inline void Swap(register node*); inline void Invert(register node*); inline void Replace(register node*,register int); inline void updata(node* p) { if(p==__) return; p->size=1+get_size(p->ls)+get_size(p->rs); p->sum=get_sum(p->ls)+get_sum(p->rs)+p->x; p->min_l=min(get_min_l(p->ls),get_sum(p->ls)+p->x+get_min_l(p->rs)); p->max_r=max(get_max_r(p->rs),get_sum(p->rs)+p->x+get_max_r(p->ls)); p->max_l=max(get_max_l(p->ls),get_sum(p->ls)+p->x+get_max_l(p->rs)); p->min_r=min(get_min_r(p->rs),get_sum(p->rs)+p->x+get_min_r(p->ls)); } inline void push_down(node* p) { if(p==__) return; if(p->sp!=0){ Swap(p->ls);Swap(p->rs);p->sp=0; } if(p->rp!=0){ register int op=p->rp; Replace(p->ls,op);Replace(p->rs,op); p->rp=0; } if(p->ip!=0){ Invert(p->ls);Invert(p->rs); p->ip=0; } return ; } inline void rotate(node* p) { register int k=get_son(p); register node* q=p->fa; push_down(q);push_down(p); q->son[k]=p->son[k^1]; if(p->son[k^1]!=__) p->son[k^1]->fa=q; if(q->fa!=__) q->fa->son[get_son(q)]=p; p->fa=q->fa; q->fa=p; p->son[k^1]=q; updata(q); return ; } inline void Splay(node* p,node* goal) { if(p==goal) return; if(goal==__) rt=p; while(p->fa!=goal){ if(p->fa->fa==goal) {rotate(p);break;} if(get_son(p)==get_son(p->fa)) rotate(p->fa),rotate(p); else rotate(p),rotate(p); } updata(p); return ; } inline int input() { char ch=getchar();while(ch!='('&&ch!=')') ch=getchar(); return ch=='('? 1:-1; } inline void build(node* &p,int l,int r) { if(l>r) return; p=new node(); register int mid=l+r>>1; p->x=opp[mid];p->min_l=min(0,p->x);p->max_r=max(0,p->x); p->sum=p->x;p->max_l=p->max_r;p->min_r=p->min_l; build(p->ls,l,mid-1); build(p->rs,mid+1,r); if(p->ls!=__) p->ls->fa=p;//!! if(p->rs!=__) p->rs->fa=p;//!! updata(p); } inline node* Find(int x) { if(x<1||x>n) return __; register node* p=rt; while(x&&p!=__){ push_down(p); register int sz=get_size(p->ls); if(sz>=x) p=p->ls; else {x-=sz+1;if(!x) return p;p=p->rs;} } return p; } node *L,*R; inline node* Get(register int l,register int r) { L=Find(l-1);R=Find(r+1); register node* p=__; if(L==__&&R==__) p=rt; else if(L==__) Splay(R,__),p=rt->ls; else if(R==__) Splay(L,__),p=rt->rs; else Splay(L,__),Splay(R,rt),p=rt->rs->ls; return p; } inline void Replace(register node* p,register int op) { if(p==__) return; p->ip=0;//都改成一个东西了就不要反转了 p->x=op;p->sum=op*p->size; p->min_l=min(0,p->sum); p->max_r=max(0,p->sum); p->max_l=p->max_r; p->min_r=p->min_l; p->rp=op; } inline void Swap(register node* p) { if(p==__) return; p->sp^=1; swap(p->ls,p->rs); swap(p->max_l,p->max_r); swap(p->min_l,p->min_r); } inline void Invert(register node* p) { if(p==__) return; p->ip^=1;p->sum=~p->sum+1;p->x=~p->x+1; swap(p->min_l,p->max_l);swap(p->min_r,p->max_r); p->min_l=~p->min_l+1;p->max_l=~p->max_l+1; p->min_r=~p->min_r+1;p->max_r=~p->max_r+1;//反转了就取个相反数即可 return ; } inline int Query(register node* p) { return ((p->max_r+1>>1)-(p->min_l-1)/2); } int main() { n=read();m=read();for(int i=1;i<=n;i++) opp[i]=input(); build(rt,1,n); register int l,r; for(register int i=1;i<=m;i++){ char ch=getchar(); while(ch!='R'&&ch!='Q'&&ch!='S'&&ch!='I') ch=getchar(); l=read();r=read(); register node* p=Get(l,r); if(ch=='R') Replace(p,input()); else if(ch=='S') Swap(p); else if(ch=='I') Invert(p); else printf("%d\n",Query(p)); if(R!=__) updata(R); if(L!=__) updata(L); } }
相关文章推荐
- BZOJ 2329 HNOI2011 括号修复 Splay
- BZOJ2329: [HNOI2011]括号修复
- [HNOI2011][bzoj 2329] 括号修复 [splay+前缀和]
- [BZOJ2329][HNOI2011]括号修复-splay
- BZOJ 2329 HNOI 2011 括号修复 —— 标记处理的原则
- Bzoj2329: [HNOI2011]括号修复
- ●BZOJ 2329 [HNOI2011]括号修复.cpp
- BZOJ 2329: [HNOI2011]括号修复( splay )
- bzoj 2329 [HNOI2011]括号修复 splay
- bzoj2329 [HNOI2011]括号修复
- bzoj2329 [HNOI2011]括号修复
- [BZOJ2329][HNOI2011]括号修复
- BZOJ 2329: [HNOI2011]括号修复 [splay 括号]
- BZOJ2329 [HNOI2011]括号修复
- 【bzoj2329】[HNOI2011]括号修复 Splay
- bzoj2329 [HNOI2011]括号修复(splay)
- 【BZOJ】2329: [HNOI2011]括号修复(splay+特殊的技巧)
- BZOJ 2209: [Jsoi2011]括号序列&&BZOJ 2329: [HNOI2011]括号修复
- 【bzoj2329】[HNOI2011]括号修复
- bzoj千题计划222:bzoj2329: [HNOI2011]括号修复(fhq treap)