您的位置:首页 > 其它

FZU 2105 Digits Count(WA)

2013-05-09 23:23 351 查看
裸线段树,目前WA中。

如果用离散化的话,就跟 poj 2528 Mayor’s posters 一样中间需要插点,之前样例一直跑不对就是这个原因。

但这个做法依然不对,我这种做法相当于默认为位运算的运算顺序不影响结果,实际上对于位运算来说,混合运算不同的运算顺序不一定得到相同的结果。

虽然花了很长时间很大功夫也没做出来,但是知道自己错在哪里也是一种收获。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>

#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1

using namespace std;

const int MAXN = 1e6;
const int MAXSIZE = 222222;
const int ANDFLAG = (1 << 16) - 1;

struct Seg
{
int cnt[16];
int andFlag;
int orFlag;
int xorFlag;
bool first;
};

struct oper
{
char str[5];
int a, b, val;
};

int N, Q;
Seg ss[ MAXSIZE << 2 ];
oper op[ MAXSIZE];
int num[MAXN];
int X[MAXSIZE << 2];

void PushUp( int rt )
{
int lc = rt << 1;
int rc = rt << 1 | 1;
for ( int i = 0; i < 16; ++i )
ss[rt].cnt[i] = ss[lc].cnt[i] + ss[rc].cnt[i];
return;
}

void change( int c, int val, int *nn )
{
int temp[16] = { 0 };

for ( int i = 0; i < 16; ++i )
{
int tp = i;
if ( c == 1 ) tp &= val;
else if ( c == 3 ) tp ^= val;
else if ( c == 2 ) tp |= val;
//   printf( "pre nn[%d]=%d tp=%d\n", i, nn[i], tp );
temp[tp] += nn[i];
}

for ( int i = 0; i < 16; ++i )
{
//  printf("nn[%d] = %d\n", i, nn[i] );
nn[i] = temp[i];
}

return;
}

void PushDown( int rt )
{
int lc = rt << 1;
int rc = rt << 1 | 1;

if ( ss[rt].andFlag != ANDFLAG )
{
ss[lc].andFlag = ss[rc].andFlag = ss[rt].andFlag;
change( 1, ss[rt].andFlag, ss[rt].cnt );
ss[rt].andFlag = ANDFLAG;
}

if ( ss[rt].first == false )
{
ss[lc].first = ss[rc].first = ss[rt].first;
ss[lc].xorFlag = ss[rc].xorFlag = ss[rt].xorFlag;
change( 3, ss[rt].xorFlag, ss[rt].cnt );

ss[rt].first = true;
ss[rt].xorFlag = 0;
}

if ( ss[rt].orFlag != 0 )
{
ss[lc].orFlag = ss[rc].orFlag = ss[rt].orFlag;
change( 2, ss[rt].orFlag, ss[rt].cnt );
ss[rt].orFlag = 0;
}

return;
}

int query( int L, int R, int l, int r, int rt )
{
if ( L <= l && r <= R )
{
PushDown(rt);
//printf( "(%d, %d)\n", l, r );
int sum = 0;

//printf("query(%d, %d)\n", l, r);
for ( int i = 0; i < 16; ++i )
{
//  printf( "%d %d\n", i, ss[rt].cnt[i] );
sum += i * ss[rt].cnt[i];
}

return sum;
}

PushDown( rt );
int m = ( l + r ) >> 1;

int tpL = 0, tpR = 0;
if ( L <= m ) tpL = query( L, R, lson );
if ( R > m ) tpR = query( L, R, rson );

PushUp(rt);

// printf( "(%d, %d)=%d\n", l, r, tpL + tpR );
return tpL + tpR;
}

void Update( int L, int c, int l, int r, int rt )   //插点
{
if ( L == l && L == r )
{
++ss[rt].cnt[c];
return;
}

int m = ( l + r ) >> 1;
if ( L <= m ) Update( L, c, lson );
else Update( L, c, rson );

PushUp( rt );
return;
}

void UpdateFlag( int L, int R, int c, int val, int l, int r, int rt ) //操作
{
if ( L <= l && r <= R )
{
if ( c == 1 )               //与操作
ss[rt].andFlag &= val;
else if ( c == 2 )          //或操作
ss[rt].orFlag |= val;
else                        //异或操作
{
if ( ss[rt].first )
{
ss[rt].first = false;
ss[rt].xorFlag = val;
}
else ss[rt].xorFlag ^= val;
}
PushDown(rt);

// printf( "update(%d, %d)\n", l, r );
//for ( int i = 0; i < 16; ++i )
// {
//   printf( "%d %d\n", i, ss[rt].cnt[i] );
//  sum += i * ss[rt].cnt[i];
//}

return;
}

PushDown(rt);
int m = ( l + r ) >> 1;
if ( L <= m ) UpdateFlag( L, R, c, val, lson );
if ( R > m )  UpdateFlag( L, R, c, val, rson );
PushUp(rt);

return;
}

void build( int l, int r, int rt )   //建树初始化
{
memset( ss[rt].cnt, 0, sizeof(ss[rt].cnt));
ss[rt].andFlag = ANDFLAG;
ss[rt].orFlag = 0;
ss[rt].first = true;
ss[rt].xorFlag = 0;

if ( l == r ) return;

int m = ( l + r ) >> 1;
build( lson );
build( rson );

return;
}

int BinSearch( int *nn, int tar, int x, int y )  //二分查找
{
int mid;
while ( x < y )
{
mid = ( x + y ) >> 1;
if ( nn[mid] == tar ) return mid;
if ( nn[mid] > tar ) y = mid - 1;
else x = mid + 1;
}
return x;
}

int main()
{
int T;
//  freopen( "s.out", "w", stdout );
scanf( "%d", &T );
while ( T-- )
{
scanf( "%d%d", &N, &Q );
for ( int i = 0; i < N; ++i )    //保存每个数
scanf( "%d", &num[i] );

int nn = 0;
for ( int i = 0; i < Q; ++i )   //保存
{
int a, b, val;
scanf( "%s", op[i].str );
if ( op[i].str[0] == 'S' ) scanf( "%d%d", &a, &b );
else scanf( "%d%d%d", &val, &a, &b );

op[i].a = a;
op[i].b = b;
op[i].val = val;

X[ nn++ ] = a;
X[ nn++ ] = b;
}
sort( X, X + nn );
int m = 1;

for ( int i = 1; i < nn; ++i )   //去除重点
if ( X[i] != X[i - 1] ) X[ m++ ] = X[i];

for ( int i = m - 1; i > 0; --i )   //加点
if ( X[i] != X[i - 1] + 1 )
X[m++] = X[i - 1] + 1;

sort( X, X + m );
/*
for ( int i = 0; i < m; ++i ) printf( "%d ", X[i] );
puts("");
*/
build( 0, m, 1 );    //建树
for ( int i = 0; i < N; ++i )   //插点
{
int addr = BinSearch( X, i, 0, m );
//  printf("addr = %d\n", addr );
Update( addr, num[i], 0, m, 1 );
}

for ( int i = 0; i < Q; ++i )
{
int a = BinSearch( X, op[i].a , 0, m );
int b = BinSearch( X, op[i].b , 0, m );

if ( op[i].str[0] == 'A' ) UpdateFlag( a, b, 1, op[i].val, 0, m, 1 );
else if ( op[i].str[0] == 'O' )
{
//     printf("(%d, %d)\n", a, b );
UpdateFlag( a, b, 2, op[i].val, 0, m, 1 );
}
else if ( op[i].str[0] == 'X' ) UpdateFlag( a, b, 3, op[i].val, 0, m, 1 );
else printf("%d\n", query( a, b, 0, m, 1 ) );
// puts("");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: