裸线段树区间合并,题目本身不难,就是细节处理比较麻烦。
因为涉及到异或运算,所以连续0和连续1的个数都要记录一下。
操作的懒惰标记我只用了一个flag,注意flag更新时的细节,我分了三种情况:
flag == -1 或者 当前操作为0或1:更新时直接赋值。因为0, 1操作都可以直接覆盖前面的操作。
flag == 0或1,当前操作为2(xor):flag ^= 1。前面标记过0或1,当前操作为异或,那么改变flag标记
flag == 2,当前操作为2(xor): flag = -1。前面只出现过异或运算,没出现过0,1运算。因为异或两次相当于没异或,所以清除标记即可。
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 6 using namespace std; 7 8 #define lson l, m, rt << 1 9 #define rson m + 1, r, rt << 1 | 1 10 11 const int MAXN = 100010; 12 13 int N, Q, maxLen; 14 int cnt[ MAXN << 2 ]; // 1 的个数 15 int len[ MAXN << 2 ]; //最长连续1长度 16 int len0[ MAXN << 2 ]; //最长连续0长度 17 int flag[ MAXN << 2 ]; //懒惰标记 18 int Llen[ MAXN << 2 ]; //左端连续1长度 19 int Llen0[ MAXN << 2 ]; //左端连续0长度 20 int Rlen[ MAXN << 2 ]; //右端连续1长度 21 int Rlen0[ MAXN << 2 ]; //右端连续0长度 22 bool Lnode[ MAXN << 2 ]; //左端点是否为1 23 bool Rnode[ MAXN << 2 ]; //右端点是否为1 24 25 void PushUp( int rt, int l, int r, int m ) 26 { 27 int lc = rt << 1; 28 int rc = rt << 1 | 1; 29 30 cnt[rt] = cnt[lc] + cnt[rc]; 31 32 Lnode[rt] = Lnode[lc]; 33 Rnode[rt] = Rnode[rc]; 34 35 Llen[rt] = Llen[lc]; 36 Rlen[rt] = Rlen[rc]; 37 38 Llen0[rt] = Llen0[lc]; 39 Rlen0[rt] = Rlen0[rc]; 40 41 if ( Llen[lc] == m - l + 1 ) Llen[rt] += Llen[rc]; 42 if ( Llen0[lc] == m - l + 1 ) Llen0[rt] += Llen0[rc]; 43 44 if ( Rlen[rc] == r - m ) Rlen[rt] += Rlen[lc]; 45 if ( Rlen0[rc] == r - m ) Rlen0[rt] += Rlen0[lc]; 46 47 len[rt] = max( len[lc], len[rc] ); 48 len0[rt] = max( len0[lc], len0[rc] ); 49 if ( Rnode[lc] && Lnode[rc] ) 50 { 51 len[rt] = max( len[rt], Rlen[lc] + Llen[rc] ); 52 } 53 54 if ( !Rnode[lc] && !Lnode[rc] ) 55 { 56 len0[rt] = max( len0[rt], Rlen0[lc] + Llen0[rc] ); 57 } 58 59 return; 60 } 61 62 void chuli( int op, int rt, int l, int r ) 63 { 64 if ( op == 0 ) 65 { 66 cnt[rt] = 0; 67 Lnode[rt] = Rnode[rt] = false; 68 len[rt] = Llen[rt] = Rlen[rt] = 0; 69 len0[rt] = Llen0[rt] = Rlen0[rt] = r - l + 1; 70 } 71 else if ( op == 1 ) 72 { 73 cnt[rt] = r - l + 1; 74 Lnode[rt] = Rnode[rt] = true; 75 len[rt] = Llen[rt] = Rlen[rt] = r - l + 1; 76 len0[rt] = Llen0[rt] = Rlen0[rt] = 0; 77 } 78 else 79 { 80 cnt[rt] = r - l + 1 - cnt[rt]; 81 Lnode[rt] = !Lnode[rt]; 82 Rnode[rt] = !Rnode[rt]; 83 swap( Llen[rt], Llen0[rt] ); 84 swap( Rlen[rt], Rlen0[rt] ); 85 swap( len[rt], len0[rt] ); 86 } 87 return; 88 } 89 90 void fuzhi( int rt, int c, int l, int r ) 91 { 92 if ( flag[rt] == -1 ) 93 { 94 flag[rt] = c; 95 return; 96 } 97 if ( c == 2 ) 98 { 99 if ( flag[rt] == 0 || flag[rt] == 1 ) flag[rt] ^= 1; 100 else if ( flag[rt] == 2 ) flag[rt] = -1; 101 } 102 else flag[rt] = c; 103 104 return; 105 } 106 107 void PushDown( int rt, int l, int r, int m ) 108 { 109 int lc = rt << 1; 110 int rc = rt << 1 | 1; 111 if ( flag[rt] != -1 ) 112 { 113 if ( flag[rt] == 0 || flag[rt] == 1 ) flag[lc] = flag[rc] = flag[rt]; 114 else 115 { 116 fuzhi( lc, flag[rt], l, m ); 117 fuzhi( rc, flag[rt], m + 1, r ); 118 } 119 chuli( flag[lc], lc, l, m ); 120 chuli( flag[rc], rc, m + 1, r ); 121 flag[rt] = -1; 122 } 123 return; 124 } 125 126 void Build( int l, int r, int rt ) 127 { 128 flag[rt] = -1; 129 if ( l == r ) 130 { 131 int num; 132 scanf( "%d", &num ); 133 if ( num == 1 ) 134 { 135 cnt[rt] = 1; 136 Llen[rt] = Rlen[rt] = len[rt] = 1; 137 Llen0[rt] = Rlen0[rt] = len0[rt] = 0; 138 Lnode[rt] = Rnode[rt] = true; 139 } 140 else 141 { 142 cnt[rt] = 0; 143 Llen[rt] = Rlen[rt] = len[rt] = 0; 144 Llen0[rt] = Rlen0[rt] = len0[rt] = 1; 145 Lnode[rt] = Rnode[rt] = false; 146 } 147 return; 148 } 149 150 int m = ( l + r ) >> 1; 151 Build( lson ); 152 Build( rson ); 153 PushUp( rt, l, r, m ); 154 155 return; 156 } 157 158 void Update( int L ,int R, int c, int l, int r, int rt ) 159 { 160 int m = ( l + r ) >> 1; 161 162 if ( L <= l && r <= R ) 163 { 164 fuzhi( rt, c, l, r ); 165 chuli( flag[rt], rt, l, r ); 166 return; 167 } 168 169 PushDown( rt, l, r, m ); 170 171 if ( L <= m ) Update( L, R, c, lson ); 172 if ( R > m ) Update( L, R, c, rson ); 173 PushUp( rt, l, r, m ); 174 175 return; 176 } 177 178 int Query( int L, int R, int l, int r, int rt ) 179 { 180 181 int m = ( l + r ) >> 1; 182 if ( L <= l && r <= R ) 183 { 184 maxLen = max( maxLen, len[rt] ); 185 return cnt[rt]; 186 } 187 188 PushDown( rt, l, r, m ); 189 190 int ret = 0; 191 if ( L <= m ) ret += Query( L, R, lson ); 192 if ( R > m ) ret += Query( L, R, rson ); 193 194 PushUp( rt, l, r, m ); 195 196 if ( Lnode[rt << 1 | 1] && Rnode[rt << 1] ) 197 maxLen = max( maxLen, min( Llen[rt << 1 | 1], R - m ) + min( Rlen[ rt << 1 ], m - L + 1 ) ); 198 199 200 return ret; 201 } 202 203 int main() 204 { 205 //freopen( "in2.txt", "r", stdin ); 206 //freopen( "out.txt", "w", stdout ); 207 int T; 208 scanf( "%d", &T ); 209 while ( T-- ) 210 { 211 scanf( "%d%d", &N, &Q ); 212 Build( 0, N - 1, 1 ); 213 while ( Q-- ) 214 { 215 int op, a, b; 216 scanf( "%d%d%d", &op, &a, &b ); 217 { 218 if ( op < 3 ) 219 Update(a, b, op, 0, N - 1, 1 ); 220 else 221 { 222 maxLen = 0; 223 int ans = Query( a, b, 0, N - 1, 1 ); 224 if ( op == 3 ) printf( "%d\n", ans ); 225 else printf( "%d\n", maxLen ); 226 } 227 } 228 } 229 } 230 return 0; 231 }