因为0-15二进制下最大是1111,所以可以每个区间记录一下各个位上1的个数,这样不管是对于操作也好还是求和也好都简便了许多。
PS1.感谢薛神提点。
PS2.注意细节
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 5 #define lson l, m, rt << 1 6 #define rson m + 1, r, rt << 1 | 1 7 8 const int MAXN = 1000002; 9 10 int cnt[ MAXN << 2 ][4]; 11 int flag[ MAXN << 2 ][4]; 12 int Xor[ MAXN << 2 ][4]; //标记该位是否需要异或 13 14 int N, Q; 15 16 void PushUp( int rt ) 17 { 18 int lc = rt << 1; 19 int rc = rt << 1 | 1; 20 for ( int i = 0; i < 4; ++i ) 21 cnt[rt][i] = cnt[lc][i] + cnt[rc][i]; 22 return; 23 } 24 25 void PushDown( int rt, int m, int l, int r ) 26 { 27 int lc = rt << 1; 28 int rc = rt << 1 | 1; 29 for ( int i = 0; i < 4; ++i ) 30 { 31 if ( flag[rt][i] != -1 ) 32 { 33 flag[lc][i] = flag[rc][i] = flag[rt][i]; 34 cnt[lc][i] = flag[lc][i] * ( m - l + 1 ); 35 cnt[rc][i] = flag[rc][i] * ( r - m ); 36 flag[rt][i] = -1; 37 Xor[lc][i] = Xor[rc][i] = 0; 38 } 39 else if ( Xor[rt][i] ) 40 { 41 cnt[lc][i] = m - l + 1 - cnt[lc][i]; 42 cnt[rc][i] = r - m - cnt[rc][i]; 43 44 if ( flag[lc][i] != -1 ) flag[lc][i] ^= 1; 45 else Xor[lc][i] ^= 1; 46 47 if ( flag[rc][i] != -1 ) flag[rc][i] ^= 1; 48 else Xor[rc][i] ^= 1; 49 50 Xor[rt][i] = 0; 51 } 52 } 53 } 54 55 int Query( int L, int R, int l, int r, int rt ) 56 { 57 if ( L <= l && r <= R ) 58 { 59 int sum = 0; 60 for ( int i = 0; i < 4; ++i ) 61 { 62 sum += ( 1 << i ) * cnt[rt][i]; 63 // printf( "cnt[%d]=%d\n", i, cnt[rt][i] ); 64 } 65 return sum; 66 } 67 68 int m = ( l + r ) >> 1; 69 int ret = 0; 70 71 PushDown( rt, m, l, r ); 72 73 if ( L <= m ) ret += Query( L, R, lson ); 74 if ( R > m ) ret += Query( L, R, rson ); 75 76 PushUp( rt ); 77 return ret; 78 } 79 80 void AND( int rt, int l, int r, int opn ) 81 { 82 for ( int i = 0; i < 4; ++i ) 83 { 84 if ( ( 1 << i ) & opn ) continue; 85 flag[rt][i] = 0; 86 cnt[rt][i] = 0; 87 Xor[rt][i] = 0; 88 } 89 return; 90 } 91 92 void OR( int rt, int l, int r, int opn ) 93 { 94 for ( int i = 0; i < 4; ++i ) 95 { 96 if ( !( (1 << i) & opn ) ) continue; 97 flag[rt][i] = 1; 98 cnt[rt][i] = r - l + 1; 99 Xor[rt][i] = 0; 100 } 101 return; 102 } 103 104 void XOR( int rt, int l, int r, int opn ) 105 { 106 for ( int i = 0; i < 4; ++i ) 107 { 108 if ( !( ( 1 << i ) & opn ) ) continue; 109 cnt[rt][i] = r - l + 1 - cnt[rt][i]; 110 // printf( "**cnt[%d]=%d\n", i, cnt[rt][i] ); 111 if ( flag[rt][i] != -1 ) flag[rt][i] ^= 1; 112 else Xor[rt][i] ^= 1; 113 } 114 return; 115 } 116 117 void Update( int L, int R, int c, int opn, int l, int r, int rt ) 118 { 119 if ( L <= l && r <= R ) 120 { 121 if ( c == 1 ) AND( rt, l, r, opn ); 122 else if ( c == 2 ) OR( rt, l, r, opn ); 123 else XOR( rt, l, r, opn ); 124 125 return; 126 } 127 int m = ( l + r ) >> 1; 128 PushDown( rt, m, l, r ); 129 130 if ( L <= m ) Update( L, R, c, opn, lson ); 131 if ( R > m ) Update( L, R, c, opn, rson ); 132 PushUp( rt ); 133 return; 134 } 135 136 void build( int l, int r, int rt ) 137 { 138 for ( int i = 0; i < 4; ++i ) 139 { 140 flag[rt][i] = -1; 141 Xor[rt][i] = 0; 142 } 143 144 if ( l == r ) 145 { 146 int a; 147 scanf( "%d", &a ); 148 for( int i = 0; i < 4; ++i ) 149 if ( a & ( 1 << i ) ) cnt[rt][i] = 1; 150 else cnt[rt][i] = 0; 151 return; 152 } 153 int m = ( l + r ) >> 1; 154 build( lson ); 155 build( rson ); 156 PushUp( rt ); 157 return; 158 } 159 160 int main() 161 { 162 // freopen( "s.out", "w", stdout ); 163 int T; 164 scanf( "%d", &T ); 165 while ( T-- ) 166 { 167 scanf( "%d%d", &N, &Q ); 168 build( 0, N - 1, 1 ); 169 while ( Q-- ) 170 { 171 int a, b, opn; 172 char str[6]; 173 scanf( "%s", str ); 174 if ( str[0] == 'S' ) 175 { 176 scanf( "%d%d", &a, &b ); 177 printf( "%d\n", Query( a, b, 0, N - 1, 1 ) ); 178 } 179 else 180 { 181 scanf("%d%d%d", &opn, &a, &b ); 182 if ( str[0] == 'A' ) Update( a, b, 1, opn, 0, N - 1, 1 ); 183 else if ( str[0] == 'O' ) Update( a, b, 2, opn, 0, N - 1, 1 ); 184 else Update( a, b, 3, opn, 0, N - 1, 1 ); 185 } 186 } 187 } 188 return 0; 189 }