您的位置:首页 > 其它

FZU 2105 Digits Count(AC)

2013-05-10 12:50 465 查看
因为0-15二进制下最大是1111,所以可以每个区间记录一下各个位上1的个数,这样不管是对于操作也好还是求和也好都简便了许多。

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: