FZU 2105 Digits Count(WA)
2013-05-09 23:23
351 查看
裸线段树,目前WA中。
如果用离散化的话,就跟 poj 2528 Mayor’s posters 一样中间需要插点,之前样例一直跑不对就是这个原因。
但这个做法依然不对,我这种做法相当于默认为位运算的运算顺序不影响结果,实际上对于位运算来说,混合运算不同的运算顺序不一定得到相同的结果。
虽然花了很长时间很大功夫也没做出来,但是知道自己错在哪里也是一种收获。
如果用离散化的话,就跟 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; }
相关文章推荐
- FZU 2105-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 线段树
- [FZU 2105 Digits Count] 线段树区间的复合操作
- FZU/FOJ 2105 Problem 2105 Digits Count 成段更新
- fzu 2105 Digits Count(成段更新)
- FZU-2105 Digits Count(线段树)
- FZU 2105 Digits Count(AC)
- FZU - 2105 Digits Count (线段树成段更新)
- FZU 2105 Digits Count 区间更新
- FZU 2105 Digits Count(线段树区间修改)
- FZU2105-Digits Count(线段树区间)
- fzu 2105 Digits Count (线段树区间更新)
- FZU2105 Digits Count(经典 线段树)
- fzu 2105 Digits Count 线段树
- fzu 2105 Digits Count ( 线段树 ) from 第三届福建省大学生程序设计竞赛