bzoj 2209 括号序列
反转操作 + 翻转操作 = 对称操作
因为上面三个操作都是自己的逆操作,所以我们只需要实现对称操作和反转操作,就可以搞定翻转操作.
1 #include <cstdio> 2 #include <algorithm> 3 #define N 100010 4 using namespace std; 5 6 struct Node { 7 int siz, val, clf[2], crg[2], rtag, etag; 8 Node *ch[2], *par; 9 void update() { 10 int v; 11 v = (ch[0]?ch[0]->crg[0]:0) + val - (ch[1]?ch[1]->clf[0]:0); 12 clf[0] = (ch[0]?ch[0]->clf[0]:0), crg[0] = (ch[1]?ch[1]->crg[0]:0); 13 if( v>0 ) crg[0]+=v; 14 else clf[0]+=-v; 15 v = (ch[0]?ch[0]->crg[1]:0) + (-val) - (ch[1]?ch[1]->clf[1]:0); 16 clf[1] = (ch[0]?ch[0]->clf[1]:0), crg[1] = (ch[1]?ch[1]->crg[1]:0); 17 if( v>0 ) crg[1]+=v; 18 else clf[1]+=-v; 19 siz = (ch[0]?ch[0]->siz:0) + 1 + (ch[1]?ch[1]->siz:0); 20 } 21 void pushdown() { 22 if( rtag ) { 23 if( ch[0] ) ch[0]->reverse(); 24 if( ch[1] ) ch[1]->reverse(); 25 rtag = 0; 26 } 27 if( etag ) { 28 if( ch[0] ) ch[0]->exchange(); 29 if( ch[1] ) ch[1]->exchange(); 30 etag = 0; 31 } 32 } 33 void reverse() { 34 swap( ch[0], ch[1] ); 35 swap( clf[0], crg[1] ); 36 swap( clf[1], crg[0] ); 37 rtag ^= 1; 38 } 39 void exchange() { 40 swap( clf[0], clf[1] ); 41 swap( crg[0], crg[1] ); 42 val = -val; 43 etag ^= 1; 44 } 45 }pool[N], *tail=pool, *root; 46 47 int n, m; 48 char buf[N]; 49 50 Node *find( int pos ) { 51 Node *nd = root; 52 pos++; 53 while(1) { 54 nd->pushdown(); 55 int lz = nd->ch[0]?nd->ch[0]->siz:0; 56 if( pos<=lz ) { 57 nd=nd->ch[0]; 58 } else if( pos==lz+1 ){ 59 return nd; 60 } else { 61 pos -= lz+1; 62 nd=nd->ch[1]; 63 } 64 } 65 } 66 void rotate( Node *nd, int d ) { 67 Node *p = nd->par; 68 Node *s = nd->ch[!d]; 69 Node *ss = s->ch[d]; 70 71 if( !p ) root=s; 72 else p->ch[ nd==p->ch[1] ] = s; 73 if( s ) s->ch[d] = nd; 74 nd->ch[!d] = ss; 75 76 nd->par = s; 77 s->par = p; 78 if( ss ) ss->par = nd; 79 80 nd->update(); 81 s->update(); 82 } 83 void bigpush( Node *nd ) { 84 if( !nd ) return; 85 bigpush(nd->par); 86 nd->par->pushdown(); 87 } 88 void splay( Node *nd, Node *top=0 ) { 89 while( nd->par!=top ) { 90 Node *p = nd->par; 91 int nl = nd==p->ch[0]; 92 if( p->par==top ) { 93 rotate( p, nl ); 94 } else { 95 Node *pp = p->par; 96 int pl = p==pp->ch[0]; 97 if( nl==pl ) { 98 rotate( pp, pl ); 99 rotate( p, nl ); 100 } else { 101 rotate( p, nl ); 102 rotate( pp, pl ); 103 } 104 } 105 } 106 } 107 Node *fetch( int lf, int rg ) { 108 Node *nl = find(lf-1); 109 Node *nr = find(rg+1); 110 splay(nl); 111 splay(nr,nl); 112 return nr->ch[0]; 113 } 114 Node *newnode( Node *par, int v ) { 115 Node *nd = ++tail; 116 nd->par = par; 117 nd->ch[0] = nd->ch[1] = 0; 118 nd->siz = 1; 119 nd->val = v; 120 nd->clf[0] = v==-1; 121 nd->crg[0] = v==1; 122 nd->clf[1] = -v==-1; 123 nd->crg[1] = -v==1; 124 nd->rtag = nd->etag = 0; 125 return nd; 126 } 127 Node *build( Node *par, int lf, int rg ) { 128 if( lf>rg ) return 0; 129 int mid=(lf+rg)>>1; 130 Node *nd = newnode( par, buf[mid]=='('?1:-1 ); 131 nd->ch[0] = build( nd, lf, mid-1 ); 132 nd->ch[1] = build( nd, mid+1, rg ); 133 nd->update(); 134 return nd; 135 } 136 int query( int lf, int rg ) { 137 Node *nd = fetch(lf,rg); 138 return ((nd->clf[0]+1)>>1)+((nd->crg[0]+1)>>1); 139 } 140 141 142 int main() { 143 scanf( "%d%d", &n, &m ); 144 scanf( "%s", buf+1 ); 145 buf[0] = '('; 146 buf[n+1] = ')'; 147 root = build( 0, 0, n+1 ); 148 for( int i=1,o,l,r; i<=m; i++ ) { 149 scanf( "%d%d%d", &o, &l, &r ); 150 if( o==0 ) { 151 printf( "%d\n", query(l,r) ); 152 } else if( o==1 ) { 153 fetch(l,r)->exchange(); 154 } else { 155 fetch(l,r)->reverse(); 156 } 157 } 158 }