ああああああああああああああ——散弾铳とテレキャスター 言叶の整列、アンハッピー 単身、都会の町并み 撃ち込んだ音、嫌いですか?
题目大意:给定一个括号序列,提供四种操作:
1.将一段区间内的所有括号的变成'('或者')'
2.将一段区间反转
3.将一段区间内的所有括号翻转,即'('变成‘)',')'变成'('
4.查询一段区间内要将至少多少个括号翻转才能变成一个合法的括号序列
5.没有5了我打多了
我依稀记得我刚开始打这道题的时候那还是一个阳光明媚的中午。。。中午。。。中午
题目略恶心 我们简单分析一下
比如说对于一个括号序列))(((())((
我们把所有匹配成功的括号全都删掉,得到一个简化版的括号序列:
))((((
不难发现左面都是'('右面都是')'
然后这个东西怎么维护呢?
我们令'('=1,')'=-1
那么。。。
不打了!!!麻烦死了!!!
这里只简单介绍标记的处理方式
首先当我们获得一个修改标记的时候,括号翻转标记和区间反转标记都要清零,因为这段区间已经被重新覆盖了,没必要再括号翻转和区间反转了
于是当修改标记和另两个标记共存时,一定是修改标记先获得,所以我们先下传修改标记
然后另两个标记互不干扰 随便选一个顺序下传就可以了。
最后代码
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 100100
using namespace std;
struct bracket_sequence{
int sum;
int lmax,rmax;
int lmin,rmin;
void flip()
{
sum*=-1;
swap(lmax,lmin);
swap(rmax,rmin);
lmax*=-1;
lmin*=-1;
rmax*=-1;
rmin*=-1;
}
void reverse()
{
swap(lmax,rmax);
swap(lmin,rmin);
}
bracket_sequence(int x,int siz)
{
sum=x*siz;
if(x==1)
lmax=rmax=sum,lmin=rmin=0;
else
lmin=rmin=sum,lmax=rmax=0;
}
};
bracket_sequence operator + (const bracket_sequence x,const bracket_sequence y)
{
bracket_sequence re(0,0);
re.sum=x.sum+y.sum;
re.lmax=max(x.lmax,x.sum+y.lmax);
re.rmax=max(y.rmax,y.sum+x.rmax);
re.lmin=min(x.lmin,x.sum+y.lmin);
re.rmin=min(y.rmin,y.sum+x.rmin);
return re;
}
struct abcd{
abcd *fa,*ls,*rs;
int siz,num;
bracket_sequence *bs;
int flip_mark,rev_mark,change_mark;
abcd(int x);
void Push_Up();
void Push_Down();
}*null=new abcd(0),*root=null;
abcd :: abcd(int x)
{
siz=1;
if(!x)
siz=0;
num=x;
fa=ls=rs=null;
bs=new bracket_sequence(x,siz);
flip_mark=rev_mark=change_mark=0;
}
void abcd :: Push_Up()
{
siz=ls->siz+rs->siz+1;
*bs=(*ls->bs)+bracket_sequence(num,1)+(*rs->bs);
}
void abcd :: Push_Down()
{
if(change_mark)
{
ls->change_mark=ls->num=change_mark;
rs->change_mark=rs->num=change_mark;
*ls->bs=bracket_sequence(change_mark,ls->siz);
*rs->bs=bracket_sequence(change_mark,rs->siz);
ls->flip_mark=ls->rev_mark=0;
rs->flip_mark=rs->rev_mark=0;
change_mark=0;
}
if(flip_mark)
{
ls->flip_mark^=1;
rs->flip_mark^=1;
ls->num*=-1;
rs->num*=-1;
ls->bs->flip();
rs->bs->flip();
flip_mark=0;
}
if(rev_mark)
{
ls->rev_mark^=1;
rs->rev_mark^=1;
ls->bs->reverse();
rs->bs->reverse();
swap(ls->ls,ls->rs);
swap(rs->ls,rs->rs);
rev_mark=0;
}
}
void Zig(abcd *x)
{
abcd *y=x->fa;
y->Push_Down();
x->Push_Down();
y->ls=x->rs;
x->rs->fa=y;
x->rs=y;
x->fa=y->fa;
if(y==y->fa->ls)
y->fa->ls=x;
else if(y==y->fa->rs)
y->fa->rs=x;
y->fa=x;
y->Push_Up();
if(root==y)
root=x;
}
void Zag(abcd *x)
{
abcd *y=x->fa;
y->Push_Down();
x->Push_Down();
y->rs=x->ls;
x->ls->fa=y;
x->ls=y;
x->fa=y->fa;
if(y==y->fa->ls)
y->fa->ls=x;
else if(y==y->fa->rs)
y->fa->rs=x;
y->fa=x;
y->Push_Up();
if(root==y)
root=x;
}
void Splay(abcd *x,abcd *Tar)
{
while(1)
{
abcd *y=x->fa,*z=y->fa;
if(y==Tar)
break;
if(z==Tar)
{
if(x==y->ls) Zig(x);
else Zag(x);
break;
}
if(x==y->ls)
{
if(y==z->ls)
Zig(y);
Zig(x);
}
else
{
if(y==z->rs)
Zag(y);
Zag(x);
}
}
x->Push_Up();
}
void Find(abcd *x,int y,abcd *z)
{
while(1)
{
x->Push_Down();
if(y<=x->ls->siz)
x=x->ls;
else
{
y-=x->ls->siz;
if(y==1)
break;
y--;
x=x->rs;
}
}
Splay(x,z);
}
void Insert(abcd *&x,int y,abcd *z)
{
if(x==null)
{
x=new abcd(y);
x->fa=z;
Splay(x,null);
return ;
}
x->Push_Down();
Insert(x->rs,y,x);
}
int n,m;
char s[M];
int main()
{
int i,x,y;
cin>>n>>m;
scanf("%s",s+1);
Insert(root,-2,null);
for(i=1;i<=n;i++)
Insert(root,s[i]=='('?1:-1,null);
Insert(root,2,null);
for(i=1;i<=m;i++)
{
scanf("%s%d%d",s,&x,&y);
Find(root,x,null);
Find(root,y+2,root);
abcd *temp=root->rs->ls;
if(s[0]=='R')
{
scanf("%s",s);
temp->change_mark=temp->num=(s[0]=='('?1:-1);
*temp->bs=bracket_sequence(temp->change_mark,temp->siz);
temp->flip_mark=temp->rev_mark=0;
}
else if(s[0]=='S')
{
temp->rev_mark^=1;
temp->bs->reverse();
swap(temp->ls,temp->rs);
}
else if(s[0]=='I')
{
temp->flip_mark^=1;
temp->num*=-1;
temp->bs->flip();
}
else
{
x=(int)ceil(abs(temp->bs->lmin)/2.0);
y=(int)ceil(abs(temp->bs->rmax)/2.0);
printf("%d\n", x+y );
}
}
}