您的位置:首页 > 其它

bzoj 2329: [HNOI2011]括号修复 splay

2018-04-03 19:37 423 查看

题意

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

空串是合法的。

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

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

现在给你一个长度为 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]之间的字符串至少要改变多少位才能变成合法的括号序列。改变某位是指将该位的‘(’变成‘)’或‘)’变成‘(’。注意执行操作 Query 并不改变当前的括号序列。例如:假设原来的字符串为:))())())(,那么执行操作 Query 3 6的结果为 2,因为要将位置 5 的‘)’变成‘(’并将位置 6 的‘(’变成‘)’。

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

分析

有反转和一大堆操作的一般就是大型数据结构splay

询问也是比较简单,我们发现只有

)))))))((((((((

这个的情况才要翻转

于是括号序列,套路(+1,)-1,求最小前缀和最大后缀

这个东西由于还有翻转操作,你还要维护多两个东西

就是设:

s1表示最小前缀

s2表示最大后缀

s3表示最大前缀

s4表示最大后缀

然后

invert操作就是把s1和s3对调,s2和s4对调,然后对应取反

Swap操作就是把s1和s4对调,s2和s3对调

下传标记的时候,假设下传swap标记,就不用管先后,因为只是顺序改变,内容没改变

先下传Invert标记,要把replace标记给取反

再下传replace标记,下传的时候把Invert标记和swap标记删掉

如果把顺序反了,显然会错,因为标记不断的Invert。

写了7K感人肺腑

代码

#include <bits/stdc++.h>
#define ll long long

using namespace std;

const int N = 100010;
const int mod = 1000000007;

inline int read()
4000

{
int p=0; int f=1; char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-') f=-1; ch=getchar();}
while(ch>='0' && ch<='9'){p=p*10+ch-'0'; ch=getchar();}
return p*f;
}

struct node
{
int son[2],siz,fa,c,s,s1,s2,s3,s4,tag1;
bool rev,tag2;
}tr
; int rt;

void update(int u)
{
tr[u].siz = tr[tr[u].son[0]].siz + tr[tr[u].son[1]].siz + 1;
tr[u].s = tr[tr[u].son[0]].s + tr[tr[u].son[1]].s + tr[u].c;
tr[u].s1 = min( min(tr[tr[u].son[0]].s1 , 0) , min(tr[tr[u].son[0]].s + tr[u].c , tr[tr[u].son[0]].s + tr[u].c + tr[tr[u].son[1]].s1) );
tr[u].s4 = min( min(tr[tr[u].son[1]].s4 , 0) , min(tr[tr[u].son[1]].s + tr[u].c , tr[tr[u].son[1]].s + tr[u].c + tr[tr[u].son[0]].s4) );
tr[u].s2 = max( max(tr[tr[u].son[1]].s2 , 0) , max(tr[tr[u].son[1]].s + tr[u].c , tr[tr[u].son[1]].s + tr[u].c + tr[tr[u].son[0]].s2) );
tr[u].s3 = max( max(tr[tr[u].son[0]].s3 , 0) , max(tr[tr[u].son[0]].s + tr[u].c , tr[tr[u].son[0]].s + tr[u].c + tr[tr[u].son[1]].s3) );
}

void push_down(int u)
{
if(tr[u].rev)
{
if(tr[u].son[0]) tr[tr[u].son[0]].rev^=1;
if(tr[u].son[1]) tr[tr[u].son[1]].rev^=1;

int lc = tr[u].son[0]; int rc=tr[u].son[1];

if(lc){swap(tr[lc].s1,tr[lc].s4); swap(tr[lc].s2,tr[lc].s3); swap(tr[lc].son[0],tr[lc].son[1]);}
if(rc){swap(tr[rc].s1,tr[rc].s4); swap(tr[rc].s2,tr[rc].s3); swap(tr[rc].son[0],tr[rc].son[1]);}

tr[u].rev^=1;
}

if(tr[u].tag2)
{
int lc = tr[u].son[0]; int rc = tr[u].son[1];
if(lc)
{
tr[lc].tag2^=1; tr[lc].tag1*=-1; tr[lc].c=-tr[lc].c;
swap(tr[lc].s1,tr[lc].s3); swap(tr[lc].s2,tr[lc].s4);
tr[lc].s=-tr[lc].s; tr[lc].s1=-tr[lc].s1; tr[lc].s2=-tr[lc].s2; tr[lc].s3=-tr[lc].s3; tr[lc].s4=-tr[lc].s4;
}
if(rc)
{
tr[rc].tag2^=1; tr[rc].tag1*=-1; tr[rc].c=-tr[rc].c;
swap(tr[rc].s1,tr[rc].s3); swap(tr[rc].s2,tr[rc].s4);
tr[rc].s=-tr[rc].s; tr[rc].s1=-tr[rc].s1; tr[rc].s2=-tr[rc].s2; tr[rc].s3=-tr[rc].s3; tr[rc].s4=-tr[rc].s4;
}
tr[u].tag2^=1;
}

if(tr[u].tag1!=0)
{
if(tr[u].tag1 == 1)
{
int lc = tr[u].son[0]; int rc = tr[u].son[1];
if(lc)
{
tr[lc].tag1=1; tr[lc].tag2=tr[lc].rev=0;
tr[lc].c=1; tr[lc].s=tr[lc].siz;
tr[lc].s2=tr[lc].s3=tr[lc].siz; tr[lc].s1=tr[lc].s4=0;
}

if(rc)
{
tr[rc].tag1=1; tr[rc].tag2=tr[rc].rev=0;
tr[rc].c=1; tr[rc].s=tr[rc].siz;
tr[rc].s2=tr[rc].s3=tr[rc].siz; tr[rc].s1=tr[rc].s4=0;
}
}

else
{
int lc = tr[u].son[0]; int rc = tr[u].son[1];
if(lc)
{
tr[lc].tag1=-1; tr[lc].tag2=tr[lc].rev=0;
tr[lc].c=-1; tr[lc].s=-tr[lc].siz;
tr[lc].s1=tr[lc].s4=-tr[lc].siz; tr[lc].s2=tr[lc].s3=0;
}
if(rc)
{
tr[rc].tag1=-1; tr[rc].tag2=tr[rc].rev=0;
tr[rc].c=-1; tr[rc].s=-tr[rc].siz;
tr[rc].s1=tr[rc].s4=-tr[rc].siz; tr[rc].s2=tr[rc].s3=0;
}
}

tr[u].tag1=0;
}
}

void rotate(int x)
{
int y=tr[x].fa; int z=tr[y].fa;
int a=tr[y].son[1]==x; int b=tr[z].son[1]==y;
int g=tr[x].son[1-a];
if(z) tr[z].son[b] = x; tr[x].fa=z;
tr[x].son[1-a] = y; tr[y].fa=x;
tr[y].son[a] = g; if(g) tr[g].fa=y;
update(y);
}

stack<int>s;

void preserve(int x,int anc)
{
while(x!=anc){s.push(x); x=tr[x].fa;} s.push(anc);
while(!s.empty()){push_down(s.top()),s.pop();}
}

void splay(int x,int anc)
{
preserve(x,anc);
while(tr[x].fa!=anc)
{
int y=tr[x].fa; int a=tr[y].son[1]==x;
if(tr[y].fa == anc) rotate(x);
else
{
int z=tr[y].fa; int b=tr[z].son[1]==y;
if(a==b) rotate(y);
else rotate(x);
}
}
update(x); if(anc==0) rt=x;
}

int build(int l,int r,int fa)
{
int mid = (l+r)>>1; tr[mid].fa = fa;
if(l<mid) tr[mid].son[0] = build(l,mid-1,mid);
if(mid<r) tr[mid].son[1] = build(mid+1,r,mid);
update(mid); return mid;
}

int find_rank(int u,int x)
{
push_down(u);
if(tr[tr[u].son[0]].siz + 1 == x) return u;
if(x<=tr[tr[u].son[0]].siz) return find_rank(tr[u].son[0],x);
else return find_rank(tr[u].son[1],x-tr[tr[u].son[0]].siz-1);
}

int n , m; char ss
;

int main()
{

n=read(); m=read();
for(int i=1;i<=n;i++) scanf("\n%c",&ss[i]);
for(int i=1;i<=n;i++) if(ss[i]=='(') tr[i].c=1; else tr[i].c=-1;

rt=n+1; tr[n+1].c=tr[n+2].c=0; tr[n+1].son[1] = n+2; tr[n+2].fa=n+1;
tr[n+2].son[0] = build(1,n,n+2);  update(n+2); update(n+1);

while(m--)
{
scanf("%s",ss+1);
if(ss[1] == 'R')
{
int l = read(); int r = read(); char ch=getchar();

int x = find_rank(rt,l);
int y = find_rank(rt,r+2);
splay(x,0);
splay(y,x);

int u = tr[y].son[0]; push_down(u);

if(ch == '(')
{
tr[u].tag1=1; tr[u].rev=tr[u].tag2=0; tr[u].c=1; tr[u].s=tr[u].siz;
tr[u].s2=tr[u].s3=tr[u].siz; tr[u].s1=tr[u].s4=0;
}

else
{
tr[u].tag1=-1; tr[u].rev=tr[u].tag2=0; tr[u].c=-1; tr[u].s=-tr[u].siz;
tr[u].s1=tr[u].s4=-tr[u].siz; tr[u].s2=tr[u].s3=0;
}

splay(u,0);
}
else if(ss[1] == 'Q')
{
int l = read(); int r = read();
int x = find_rank(rt,l);
int y = find_rank(rt,r+2);
splay(x,0);
splay(y,x);

int u = tr[y].son[0];
printf("%d\n",(int)(ceil((double)(-tr[u].s1) / 2.0)) + (int)(ceil((double)tr[u].s2 / 2.0)) );

}
else if(ss[1] == 'S')
{
int l = read(); int r= read();
int x = find_rank(rt,l);
int y = find_rank(rt,r+2);
splay(x,0);
splay(y,x);

int u = tr[y].son[0]; push_down(u); tr[u].rev^=1;
swap(tr[u].son[0],tr[u].son[1]);
swap(tr[u].s1,tr[u].s4); swap(tr[u].s2,tr[u].s3);

splay(u,0);
}
else if(ss[1] == 'I')
{
int l = read(); int r= read();
int x = find_rank(rt,l);
int y = find_rank(rt,r+2);
splay(x,0);
splay(y,x);

int u = tr[y].son[0]; push_down(u); tr[u].tag2^=1; tr[u].tag1*=(-1);
tr[u].c = - tr[u].c;
swap(tr[u].s1,tr[u].s3); swap(tr[u].s2,tr[u].s4);
tr[u].s1=-tr[u].s1; tr[u].s2=-tr[u].s2; tr[u].s3=-tr[u].s3; tr[u].s4=-tr[u].s4;
tr[u].s = -tr[u].s;

splay(u,0);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: