FZU 2105 Digits Count(AC)
2013-05-10 12:50
465 查看
因为0-15二进制下最大是1111,所以可以每个区间记录一下各个位上1的个数,这样不管是对于操作也好还是求和也好都简便了许多。
PS1.感谢薛神提点。
PS2.注意细节
PS1.感谢薛神提点。
PS2.注意细节
#include <cstdio> #include <cstdlib> #include <cstring> #define lson l, m, rt << 1 #define rson m + 1, r, rt << 1 | 1 const int MAXN = 1000002; int cnt[ MAXN << 2 ][4]; int flag[ MAXN << 2 ][4]; int Xor[ MAXN << 2 ][4]; //标记该位是否需要异或 int N, Q; void PushUp( int rt ) { int lc = rt << 1; int rc = rt << 1 | 1; for ( int i = 0; i < 4; ++i ) cnt[rt][i] = cnt[lc][i] + cnt[rc][i]; return; } void PushDown( int rt, int m, int l, int r ) { int lc = rt << 1; int rc = rt << 1 | 1; for ( int i = 0; i < 4; ++i ) { if ( flag[rt][i] != -1 ) { flag[lc][i] = flag[rc][i] = flag[rt][i]; cnt[lc][i] = flag[lc][i] * ( m - l + 1 ); cnt[rc][i] = flag[rc][i] * ( r - m ); flag[rt][i] = -1; Xor[lc][i] = Xor[rc][i] = 0; } else if ( Xor[rt][i] ) { cnt[lc][i] = m - l + 1 - cnt[lc][i]; cnt[rc][i] = r - m - cnt[rc][i]; if ( flag[lc][i] != -1 ) flag[lc][i] ^= 1; else Xor[lc][i] ^= 1; if ( flag[rc][i] != -1 ) flag[rc][i] ^= 1; else Xor[rc][i] ^= 1; Xor[rt][i] = 0; } } } int Query( int L, int R, int l, int r, int rt ) { if ( L <= l && r <= R ) { int sum = 0; for ( int i = 0; i < 4; ++i ) { sum += ( 1 << i ) * cnt[rt][i]; // printf( "cnt[%d]=%d\n", i, cnt[rt][i] ); } return sum; } int m = ( l + r ) >> 1; int ret = 0; PushDown( rt, m, l, r ); if ( L <= m ) ret += Query( L, R, lson ); if ( R > m ) ret += Query( L, R, rson ); PushUp( rt ); return ret; } void AND( int rt, int l, int r, int opn ) { for ( int i = 0; i < 4; ++i ) { if ( ( 1 << i ) & opn ) continue; flag[rt][i] = 0; cnt[rt][i] = 0; Xor[rt][i] = 0; } return; } void OR( int rt, int l, int r, int opn ) { for ( int i = 0; i < 4; ++i ) { if ( !( (1 << i) & opn ) ) continue; flag[rt][i] = 1; cnt[rt][i] = r - l + 1; Xor[rt][i] = 0; } return; } void XOR( int rt, int l, int r, int opn ) { for ( int i = 0; i < 4; ++i ) { if ( !( ( 1 << i ) & opn ) ) continue; cnt[rt][i] = r - l + 1 - cnt[rt][i]; // printf( "**cnt[%d]=%d\n", i, cnt[rt][i] ); if ( flag[rt][i] != -1 ) flag[rt][i] ^= 1; else Xor[rt][i] ^= 1; } return; } void Update( int L, int R, int c, int opn, int l, int r, int rt ) { if ( L <= l && r <= R ) { if ( c == 1 ) AND( rt, l, r, opn ); else if ( c == 2 ) OR( rt, l, r, opn ); else XOR( rt, l, r, opn ); return; } int m = ( l + r ) >> 1; PushDown( rt, m, l, r ); if ( L <= m ) Update( L, R, c, opn, lson ); if ( R > m ) Update( L, R, c, opn, rson ); PushUp( rt ); return; } void build( int l, int r, int rt ) { for ( int i = 0; i < 4; ++i ) { flag[rt][i] = -1; Xor[rt][i] = 0; } if ( l == r ) { int a; scanf( "%d", &a ); for( int i = 0; i < 4; ++i ) if ( a & ( 1 << i ) ) cnt[rt][i] = 1; else cnt[rt][i] = 0; return; } int m = ( l + r ) >> 1; build( lson ); build( rson ); PushUp( rt ); return; } int main() { // freopen( "s.out", "w", stdout ); int T; scanf( "%d", &T ); while ( T-- ) { scanf( "%d%d", &N, &Q ); build( 0, N - 1, 1 ); while ( Q-- ) { int a, b, opn; char str[6]; scanf( "%s", str ); if ( str[0] == 'S' ) { scanf( "%d%d", &a, &b ); printf( "%d\n", Query( a, b, 0, N - 1, 1 ) ); } else { scanf("%d%d%d", &opn, &a, &b ); if ( str[0] == 'A' ) Update( a, b, 1, opn, 0, N - 1, 1 ); else if ( str[0] == 'O' ) Update( a, b, 2, opn, 0, N - 1, 1 ); else Update( a, b, 3, opn, 0, N - 1, 1 ); } } } return 0; }
相关文章推荐
- FZU 2105 Digits Count(线段树区间修改)
- [FZU 2105 Digits Count] 线段树区间的复合操作
- FZU-2105 Digits Count (两种标记成段更新)
- fzu 2105 Digits Count(成段更新)
- fzu 2105 Digits Count (线段树区间更新)
- FZU 2105 Digits Count(WA)
- fzu 2105——Digits Count
- fzu 2105 Digits Count ( 线段树 ) from 第三届福建省大学生程序设计竞赛
- FZU-2105 Digits Count(线段树)
- FZU Problem 2105 Digits Count线段树之延迟更新(插线取线)
- FZU2105-Digits Count(线段树区间)
- FZU 2105-Digits Count(线段树延时标记)
- FZU - 2105 Digits Count (线段树成段更新)
- FZU2105 Digits Count(经典 线段树)
- FZU 2105 Digits Count(线段树)
- FZU 2105 Digits Count(按位维护线段树)
- FZU 2105 Digits Count(线段树)
- fzu 2105 Digits Count 线段树
- FZU 2105 Digits Count 区间更新
- 【FZU】2105 Digits Count 线段树