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; }
相关文章推荐
- BZOJ 2329: [HNOI2011]括号修复 [splay 括号]
- 【bzoj2329】[HNOI2011]括号修复 Splay
- BZOJ2329 HNOI2011 括号修复 splay+贪心
- BZOJ 2329 HNOI2011 括号修复 Splay
- [BZOJ2329][HNOI2011]括号修复-splay
- 【BZOJ2329/2209】[HNOI2011]括号修复/[Jsoi2011]括号序列 Splay
- [HNOI2011][bzoj 2329] 括号修复 [splay+前缀和]
- bzoj 2329 [HNOI2011]括号修复 splay
- BZOJ 2329: [HNOI2011]括号修复( splay )
- bzoj2329 [HNOI2011]括号修复(splay)
- 【bzoj2329】[HNOI2011]括号修复 splay
- BZOJ 2329 HNOI 2011 括号修复 Splay维护最大连续子段和
- bzoj千题计划222:bzoj2329: [HNOI2011]括号修复(fhq treap)
- 【BZOJ】2329: [HNOI2011]括号修复(splay+特殊的技巧)
- 【bzoj2329】[HNOI2011]括号修复
- BZOJ2329: [HNOI2011]括号修复
- 2329: [HNOI2011]括号修复 - BZOJ
- Bzoj2329: [HNOI2011]括号修复
- BZOJ2329: [HNOI2011]括号修复
- 【BZOJ-2329】[HNOI2011] 括号修复