题意:给定你长度为n的括号序列,动态对区间去反,赋值(括号),询问是否匹配,
解题思路:这个题利用到了线段数求和的性质,对‘(’赋值为1,对 ‘)’括号赋值为-1,就转化为前缀和必须大于等于0且区间和等于0,根据这个判断即可。
解题代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #define maxn 100005 5 char str[maxn]; 6 struct node{ 7 int l, r, m ; 8 int sum , c , f; 9 }tree[maxn*4]; 10 int L(int c){ 11 return c*2; 12 } 13 int R(int c){ 14 return c*2+1; 15 } 16 void fxor(int c){ 17 if(tree[c].c != 0 ){ 18 tree[c].c = -tree[c].c; 19 tree[c].sum = tree[c].c*(tree[c].r - tree[c].l + 1); 20 } 21 else { 22 tree[c].f ^= 1; 23 } 24 25 } 26 void Pushup(int c){ 27 tree[c].sum = tree[L(c)].sum + tree[R(c)].sum; 28 if(tree[L(c)].c == tree[R(c)].c && tree[L(c)].c != 0) 29 tree[c].c = tree[L(c)].c; 30 else tree[c].c = 0; 31 } 32 void Pushdown(int c){ 33 if(tree[c].c != 0 ){ 34 tree[L(c)].c = tree[R(c)].c = tree[c].c; 35 tree[L(c)].sum = tree[c].c *(tree[L(c)].r - tree[L(c)].l +1); 36 tree[R(c)].sum = tree[c].c *(tree[R(c)].r - tree[R(c)].l +1); 37 tree[R(c)].f = tree[L(c)].f = 0 ; 38 } 39 if(tree[c].f){ 40 fxor(L(c)); 41 fxor(R(c)); 42 tree[c].f = 0 ; 43 } 44 } 45 void build(int c, int p , int v) 46 { 47 tree[c].l = p ; 48 tree[c].r = v ; 49 tree[c].m = (p+v)/2; 50 tree[c].sum = 0 ; 51 tree[c].c = 0; 52 tree[c].f = 0 ; 53 if(p == v ){ 54 if(str[p] == '('){ 55 tree[c].c = 1; 56 tree[c].sum = 1; 57 } 58 else { 59 tree[c].c = -1; 60 tree[c].sum = -1; 61 } 62 return ; 63 } 64 build(L(c),p,tree[c].m); 65 build(R(c),tree[c].m+1,v); 66 Pushup(c); 67 } 68 void update(int c , int p , int v, int value){ 69 if(p <= tree[c].l && v >= tree[c].r) { 70 tree[c].c = value; 71 tree[c].f = 0 ; 72 tree[c].sum = tree[c].c * (tree[c].r - tree[c].l +1); 73 return ; 74 } 75 Pushdown(c); 76 if(v <= tree[c].m ) update(L(c),p,v,value); 77 else if(p > tree[c].m) update(R(c),p,v,value); 78 else { 79 update(L(c),p,tree[c].m,value); 80 update(R(c),tree[c].m+1,v,value); 81 } 82 Pushup(c); 83 } 84 void fan(int c, int p , int v){ 85 if(p <= tree[c].l && v >= tree[c].r) { 86 fxor(c); 87 return ; 88 } 89 Pushdown(c); 90 if(v <= tree[c].m ) fan(L(c),p,v); 91 else if(p > tree[c].m) fan(R(c),p,v); 92 else { 93 fan(L(c),p,tree[c].m); 94 fan(R(c),tree[c].m+1,v); 95 } 96 Pushup(c); 97 98 } 99 int tsum =0 ; 100 int ok = 1; 101 102 void getsum(int c, int p, int v ){ 103 if(ok == 0 ) 104 return; 105 if(p <= tree[c].l && v >= tree[c].r){ 106 if(tree[c].c != 0){ 107 tsum += tree[c].sum ; 108 if(tsum < 0 ) 109 ok = 0 ; 110 return; 111 }else { 112 Pushdown(c); 113 getsum(L(c),p,tree[c].m); 114 getsum(R(c),tree[c].m+1,v); 115 return; 116 } 117 } 118 Pushdown(c); 119 if(v <= tree[c].m) getsum(L(c),p,v); 120 else if(p > tree[c].m) getsum(R(c),p,v); 121 else { 122 getsum(L(c),p,tree[c].m); 123 getsum(R(c),tree[c].m+1,v); 124 } 125 } 126 int main() 127 { 128 int t; 129 // freopen("/home/plac/problem/input.txt","r",stdin); 130 scanf("%d",&t); 131 // freopen("/home/plac/problem/output.txt","w",stdout); 132 for(int CASE = 1; CASE <= t; CASE ++){ 133 int n ; 134 scanf("%d",&n); 135 scanf("%s",str); 136 build(1,0,n-1); 137 int q; 138 scanf("%d",&q); 139 printf("Case %d:\n",CASE); 140 while(q--) 141 { 142 int a, b ; 143 char t1[10],t2[2]; 144 scanf("%s %d %d",t1,&a,&b); 145 if(t1[0] == 'r'){ 146 fan(1,a,b); 147 }else if(t1[0] == 'q'){ 148 tsum = 0 ; 149 ok = 1; 150 getsum(1,a,b); 151 if(ok == 1 && tsum == 0 && (b-a+1)%2 == 0) 152 printf("YES\n"); 153 else 154 printf("NO\n"); 155 156 }else{ 157 scanf("%s",t2); 158 if(t2[0] == '(') 159 update(1,a,b,1); 160 else 161 update(1,a,b,-1); 162 } 163 164 } 165 printf("\n"); 166 } 167 return 0 ; 168 }
PS。这题卡常数。需要优化,我在getsum里面优化了一下就过了
if(k == 0 ) return;