裸线段树,目前WA中。
如果用离散化的话,就跟 poj 2528 Mayor’s posters 一样中间需要插点,之前样例一直跑不对就是这个原因。
但这个做法依然不对,我这种做法相当于默认为位运算的运算顺序不影响结果,实际上对于位运算来说,混合运算不同的运算顺序不一定得到相同的结果。
虽然花了很长时间很大功夫也没做出来,但是知道自己错在哪里也是一种收获。
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 6 #define lson l, m, rt << 1 7 #define rson m + 1, r, rt << 1 | 1 8 9 using namespace std; 10 11 const int MAXN = 1e6; 12 const int MAXSIZE = 222222; 13 const int ANDFLAG = (1 << 16) - 1; 14 15 struct Seg 16 { 17 int cnt[16]; 18 int andFlag; 19 int orFlag; 20 int xorFlag; 21 bool first; 22 }; 23 24 struct oper 25 { 26 char str[5]; 27 int a, b, val; 28 }; 29 30 int N, Q; 31 Seg ss[ MAXSIZE << 2 ]; 32 oper op[ MAXSIZE]; 33 int num[MAXN]; 34 int X[MAXSIZE << 2]; 35 36 void PushUp( int rt ) 37 { 38 int lc = rt << 1; 39 int rc = rt << 1 | 1; 40 for ( int i = 0; i < 16; ++i ) 41 ss[rt].cnt[i] = ss[lc].cnt[i] + ss[rc].cnt[i]; 42 return; 43 } 44 45 void change( int c, int val, int *nn ) 46 { 47 int temp[16] = { 0 }; 48 49 for ( int i = 0; i < 16; ++i ) 50 { 51 int tp = i; 52 if ( c == 1 ) tp &= val; 53 else if ( c == 3 ) tp ^= val; 54 else if ( c == 2 ) tp |= val; 55 // printf( "pre nn[%d]=%d tp=%d\n", i, nn[i], tp ); 56 temp[tp] += nn[i]; 57 } 58 59 for ( int i = 0; i < 16; ++i ) 60 { 61 // printf("nn[%d] = %d\n", i, nn[i] ); 62 nn[i] = temp[i]; 63 } 64 65 return; 66 } 67 68 void PushDown( int rt ) 69 { 70 int lc = rt << 1; 71 int rc = rt << 1 | 1; 72 73 if ( ss[rt].andFlag != ANDFLAG ) 74 { 75 ss[lc].andFlag = ss[rc].andFlag = ss[rt].andFlag; 76 change( 1, ss[rt].andFlag, ss[rt].cnt ); 77 ss[rt].andFlag = ANDFLAG; 78 } 79 80 if ( ss[rt].first == false ) 81 { 82 ss[lc].first = ss[rc].first = ss[rt].first; 83 ss[lc].xorFlag = ss[rc].xorFlag = ss[rt].xorFlag; 84 change( 3, ss[rt].xorFlag, ss[rt].cnt ); 85 86 ss[rt].first = true; 87 ss[rt].xorFlag = 0; 88 } 89 90 if ( ss[rt].orFlag != 0 ) 91 { 92 ss[lc].orFlag = ss[rc].orFlag = ss[rt].orFlag; 93 change( 2, ss[rt].orFlag, ss[rt].cnt ); 94 ss[rt].orFlag = 0; 95 } 96 97 return; 98 } 99 100 int query( int L, int R, int l, int r, int rt ) 101 { 102 if ( L <= l && r <= R ) 103 { 104 PushDown(rt); 105 //printf( "(%d, %d)\n", l, r ); 106 int sum = 0; 107 108 //printf("query(%d, %d)\n", l, r); 109 for ( int i = 0; i < 16; ++i ) 110 { 111 // printf( "%d %d\n", i, ss[rt].cnt[i] ); 112 sum += i * ss[rt].cnt[i]; 113 } 114 115 return sum; 116 } 117 118 PushDown( rt ); 119 int m = ( l + r ) >> 1; 120 121 int tpL = 0, tpR = 0; 122 if ( L <= m ) tpL = query( L, R, lson ); 123 if ( R > m ) tpR = query( L, R, rson ); 124 125 PushUp(rt); 126 127 // printf( "(%d, %d)=%d\n", l, r, tpL + tpR ); 128 return tpL + tpR; 129 } 130 131 void Update( int L, int c, int l, int r, int rt ) //插点 132 { 133 if ( L == l && L == r ) 134 { 135 ++ss[rt].cnt[c]; 136 return; 137 } 138 139 int m = ( l + r ) >> 1; 140 if ( L <= m ) Update( L, c, lson ); 141 else Update( L, c, rson ); 142 143 PushUp( rt ); 144 return; 145 } 146 147 void UpdateFlag( int L, int R, int c, int val, int l, int r, int rt ) //操作 148 { 149 if ( L <= l && r <= R ) 150 { 151 if ( c == 1 ) //与操作 152 ss[rt].andFlag &= val; 153 else if ( c == 2 ) //或操作 154 ss[rt].orFlag |= val; 155 else //异或操作 156 { 157 if ( ss[rt].first ) 158 { 159 ss[rt].first = false; 160 ss[rt].xorFlag = val; 161 } 162 else ss[rt].xorFlag ^= val; 163 } 164 PushDown(rt); 165 166 // printf( "update(%d, %d)\n", l, r ); 167 //for ( int i = 0; i < 16; ++i ) 168 // { 169 // printf( "%d %d\n", i, ss[rt].cnt[i] ); 170 // sum += i * ss[rt].cnt[i]; 171 //} 172 173 return; 174 } 175 176 PushDown(rt); 177 int m = ( l + r ) >> 1; 178 if ( L <= m ) UpdateFlag( L, R, c, val, lson ); 179 if ( R > m ) UpdateFlag( L, R, c, val, rson ); 180 PushUp(rt); 181 182 return; 183 } 184 185 void build( int l, int r, int rt ) //建树初始化 186 { 187 memset( ss[rt].cnt, 0, sizeof(ss[rt].cnt)); 188 ss[rt].andFlag = ANDFLAG; 189 ss[rt].orFlag = 0; 190 ss[rt].first = true; 191 ss[rt].xorFlag = 0; 192 193 if ( l == r ) return; 194 195 int m = ( l + r ) >> 1; 196 build( lson ); 197 build( rson ); 198 199 return; 200 } 201 202 int BinSearch( int *nn, int tar, int x, int y ) //二分查找 203 { 204 int mid; 205 while ( x < y ) 206 { 207 mid = ( x + y ) >> 1; 208 if ( nn[mid] == tar ) return mid; 209 if ( nn[mid] > tar ) y = mid - 1; 210 else x = mid + 1; 211 } 212 return x; 213 } 214 215 int main() 216 { 217 int T; 218 // freopen( "s.out", "w", stdout ); 219 scanf( "%d", &T ); 220 while ( T-- ) 221 { 222 scanf( "%d%d", &N, &Q ); 223 for ( int i = 0; i < N; ++i ) //保存每个数 224 scanf( "%d", &num[i] ); 225 226 int nn = 0; 227 for ( int i = 0; i < Q; ++i ) //保存 228 { 229 int a, b, val; 230 scanf( "%s", op[i].str ); 231 if ( op[i].str[0] == 'S' ) scanf( "%d%d", &a, &b ); 232 else scanf( "%d%d%d", &val, &a, &b ); 233 234 op[i].a = a; 235 op[i].b = b; 236 op[i].val = val; 237 238 X[ nn++ ] = a; 239 X[ nn++ ] = b; 240 } 241 sort( X, X + nn ); 242 int m = 1; 243 244 for ( int i = 1; i < nn; ++i ) //去除重点 245 if ( X[i] != X[i - 1] ) X[ m++ ] = X[i]; 246 247 for ( int i = m - 1; i > 0; --i ) //加点 248 if ( X[i] != X[i - 1] + 1 ) 249 X[m++] = X[i - 1] + 1; 250 251 sort( X, X + m ); 252 /* 253 for ( int i = 0; i < m; ++i ) printf( "%d ", X[i] ); 254 puts(""); 255 */ 256 build( 0, m, 1 ); //建树 257 for ( int i = 0; i < N; ++i ) //插点 258 { 259 int addr = BinSearch( X, i, 0, m ); 260 // printf("addr = %d\n", addr ); 261 Update( addr, num[i], 0, m, 1 ); 262 } 263 264 for ( int i = 0; i < Q; ++i ) 265 { 266 int a = BinSearch( X, op[i].a , 0, m ); 267 int b = BinSearch( X, op[i].b , 0, m ); 268 269 if ( op[i].str[0] == 'A' ) UpdateFlag( a, b, 1, op[i].val, 0, m, 1 ); 270 else if ( op[i].str[0] == 'O' ) 271 { 272 // printf("(%d, %d)\n", a, b ); 273 UpdateFlag( a, b, 2, op[i].val, 0, m, 1 ); 274 } 275 else if ( op[i].str[0] == 'X' ) UpdateFlag( a, b, 3, op[i].val, 0, m, 1 ); 276 else printf("%d\n", query( a, b, 0, m, 1 ) ); 277 // puts(""); 278 } 279 } 280 return 0; 281 }