bzoj 2209 括号匹配
我们把左右括号用-1和1来替代,那么两个不同的括号可以相互抵消,但必须保证是闭合的"()",而不是扩散的")(",这样我们维护一下左右的最小最大值,那么最小值就是孤单左括号的,最大值就是孤单右括号的数目,答案就是(|左小|+右大)/2+(|左小|+右大)%2。注意取反和翻转的不同,需要用不同的方式来维护以上4个值。
brackets
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cmath> 5 #include<cstring> 6 #define maxn 120000 7 #define inf 2147483646 8 using namespace std; 9 int c[maxn][2]; 10 int fa[maxn],key[maxn],size[maxn],sum[maxn],rev[maxn],opp[maxn],la[maxn],lb[maxn],ra[maxn],rb[maxn]; 11 int n,m,num,rot; 12 13 inline void update(int x) 14 { 15 la[x]=min(la[c[x][0]],sum[c[x][0]]+min(key[x],key[x]+la[c[x][1]])); 16 lb[x]=max(lb[c[x][0]],sum[c[x][0]]+max(key[x],key[x]+lb[c[x][1]])); 17 ra[x]=min(ra[c[x][1]],sum[c[x][1]]+min(key[x],key[x]+ra[c[x][0]])); 18 rb[x]=max(rb[c[x][1]],sum[c[x][1]]+max(key[x],key[x]+rb[c[x][0]])); 19 sum[x]=sum[c[x][0]]+sum[c[x][1]]+key[x]; 20 size[x]=size[c[x][0]]+size[c[x][1]]+1; 21 } 22 23 inline void reverse(int x) 24 { 25 if (!x) return ; 26 swap(c[x][0],c[x][1]); 27 swap(la[x],ra[x]); 28 swap(lb[x],rb[x]); 29 rev[x]^=1; 30 } 31 32 inline void oppsite(int x) 33 { 34 if (!x) return ; 35 key[x]=-key[x]; 36 sum[x]=-sum[x]; 37 int tmp; 38 tmp=la[x]; la[x]=-lb[x]; lb[x]=-tmp; 39 tmp=ra[x]; ra[x]=-rb[x]; rb[x]=-tmp; 40 opp[x]^=1; 41 } 42 43 inline void down(int x) 44 { 45 if (!x) return; 46 if (rev[x]) 47 { 48 reverse(c[x][0]); 49 reverse(c[x][1]); 50 rev[x]=0; 51 } 52 if (opp[x]) 53 { 54 oppsite(c[x][0]); 55 oppsite(c[x][1]); 56 opp[x]=0; 57 } 58 } 59 60 inline void relax(int x,int rot) 61 { 62 if (x!=rot) relax(fa[x],rot); 63 down(x); 64 } 65 66 inline void rotate(int x,int &rot) 67 { 68 int y=fa[x],z=fa[y]; 69 int p=(c[y][1]==x),q=p^1; 70 if (y==rot) rot=x; 71 else if (c[z][0]==y) c[z][0]=x; else c[z][1]=x; 72 fa[x]=z; fa[y]=x; fa[c[x][q]]=y; 73 c[y][p]=c[x][q]; c[x][q]=y; 74 update(y); 75 } 76 77 inline void splay(int x,int &rot) 78 { 79 relax(x,rot); 80 while (x!=rot) 81 { 82 int y=fa[x],z=fa[y]; 83 if (y!=rot) 84 if ((c[z][0]==y)xor(c[y][0]==x)) rotate(x,rot); else rotate(y,rot); 85 rotate(x,rot); 86 } 87 update(x); 88 } 89 90 inline int build(int l,int r) 91 { 92 int mid=(l+r)>>1,left=0,right=0; 93 if (l<mid) left=build(l,mid-1); 94 if (r>mid) right=build(mid+1,r); 95 if (left) c[mid][0]=left,fa[left]=mid; 96 if (right) c[mid][1]=right,fa[right]=mid; 97 update(mid); 98 return mid; 99 } 100 101 inline int find(int t,int k) 102 { 103 down(t); 104 if (k==size[c[t][0]]+1) return t; 105 if (k<size[c[t][0]]+1) return find(c[t][0],k); 106 if (k>size[c[t][0]]+1) return find(c[t][1],k-size[c[t][0]]-1); 107 } 108 109 110 int main() 111 { 112 //freopen("brackets.in","r",stdin); 113 scanf("%d %d\n",&n,&m); 114 char ch; 115 for (int i=2;i<=n+1;i++) 116 { 117 scanf("%c",&ch); 118 if (ch=='(') key[i]=1; else key[i]=-1; 119 } 120 rot=build(1,n+2); 121 int sign,x,y; 122 for (int i=1;i<=m;i++) 123 { 124 scanf("%d %d %d",&sign,&x,&y); 125 int l=find(rot,x), r=find(rot,y+2); 126 splay(r,rot); 127 splay(l,c[rot][0]); 128 int t=c[l][1]; 129 if (sign==0) 130 { 131 int ans=((-la[t])/2)+(rb[t]/2)+((-la[t])%2)+(rb[t]%2); 132 printf("%d\n",ans); 133 } 134 if (sign==1) oppsite(t); 135 if (sign==2) reverse(t); 136 } 137 return 0; 138 } 139 140
AC without art, no better than WA !