FZU Problem 2105 Digits Count

Problem Description

Given N integers A={A[0],A[1],...,A[N-1]}. Here we have some operations:

Operation 1: AND opn L R

Here opn, L and R are integers.

For L≤i≤R, we do A[i]=A[i] AND opn (here "AND" is bitwise operation).

Operation 2: OR opn L R

Here opn, L and R are integers.

For L≤i≤R, we do A[i]=A[i] OR opn (here "OR" is bitwise operation).

Operation 3: XOR opn L R

Here opn, L and R are integers.

For L≤i≤R, we do A[i]=A[i] XOR opn (here "XOR" is bitwise operation).

Operation 4: SUM L R

We want to know the result of A[L]+A[L+1]+...+A[R].

Now can you solve this easy problem?

Input

The first line of the input contains an integer T, indicating the number of test cases. (T≤100)

Then T cases, for any case, the first line has two integers n and m (1≤n≤1,000,000, 1≤m≤100,000), indicating the number of elements in A and the number of operations.

Then one line follows n integers A[0], A[1], ..., A[n-1] (0≤A[i]<16,0≤i<n).

Then m lines, each line must be one of the 4 operations above. (0≤opn≤15)

Output

For each test case and for each "SUM" operation, please output the result with a single line.

Sample Input

1
4 4
1 2 4 7
SUM 0 2
XOR 5 0 0
OR 6 0 3
SUM 0 2

Sample Output

7
18

Hint

A = [1 2 4 7]

SUM 0 2, result=1+2+4=7;

XOR 5 0 0, A=[4 2 4 7];

OR 6 0 3, A=[6 6 6 7];

SUM 0 2, result=6+6+6=18.

代码如下:

#include <stdio.h>
#include <string.h>
const int N = 1000005;

int c, res, a[N*4][4], flag[N*4][4], len[N*4];

void pushDown( int rt )
{
    int ls = 2 * rt; int rs = ls | 1;
    for( int i = 0; i < 4; ++i )
    {
        if( flag[rt][i] == -1 ) continue;
        if( flag[rt][i] == 0 || flag[rt][i] == 1 )
        {
            a[ls][i] = ( flag[ls][i] = flag[rt][i] ) * len[ls];
            a[rs][i] = ( flag[rs][i] = flag[rt][i] ) * len[rs];
            flag[rt][i] = -1;
        }
        else if( flag[rt][i] == 3 )
        {
            flag[rt][i] = -1;
        }
        else
        {
            a[ls][i] = len[ls] - a[ls][i];
            if( flag[ls][i] == -1 ) flag[ls][i] = 2;
            else flag[ls][i] ^= 1;
            a[rs][i] = len[rs] - a[rs][i];
            if( flag[rs][i] == -1 ) flag[rs][i] = 2;
            else flag[rs][i] ^= 1;
            flag[rt][i] = -1;
        }

    }
}

void pushUp( int rt )
{
    int ls = 2 * rt; int rs = ls | 1;
    for( int i = 0; i < 4; ++i )
        a[rt][i] = a[ls][i] + a[rs][i];
}

void build( int l, int r, int rt )
{
    len[rt] = r - l + 1;
    if( l == r )
    {
        scanf("%d", &c);
        for( int i = 0; i < 4; ++i )
            a[rt][i] = ( 1 & (c>>i) );
    }
    else
    {
        int mid = ( l + r ) / 2;
        build(l, mid, 2 * rt);
        build(mid + 1, r, 2 * rt + 1);
        pushUp( rt );
    }
}

void OR( int rt, int opn )
{
    for( int i = 0; i < 4; ++i )
    {
        if( !( (opn>>i) & 1 ) ) continue;
        flag[rt][i] = 1;
        a[rt][i] = len[rt];
    }
}

void ADD( int rt, int opn )
{
    for( int i = 0; i < 4; ++i )
    {
        if( (opn>>i) & 1 ) continue;
        flag[rt][i] = 0;
        a[rt][i] = 0;
    }
}

void XOR( int rt, int opn )
{
    for( int i = 0; i < 4; ++i )
    {
        if( !( (opn>>i) & 1 ) ) continue;
        if( flag[rt][i] == -1 ) flag[rt][i] = 2;
        else flag[rt][i] ^= 1;
        a[rt][i] = len[rt] - a[rt][i];
    }
}

void query( int l, int r, int rt, const int aa, const int bb )
{
    if( aa <= l && r <= bb )
    {
        res = res + a[rt][0] + a[rt][1] * 2 + a[rt][2] * 4 + a[rt][3] * 8;
        return;
    }
    pushDown( rt );
    int mid = ( l + r ) / 2;
    int ls = 2 * rt; int rs = ls | 1;
    if( mid >= aa ) query( l, mid, ls, aa, bb );
    if( mid < bb ) query( mid + 1, r, rs, aa, bb );
}

void update( int l, int r, int rt, const int aa, const int bb, const int opn, const int f )
{
    if( aa <= l && r <= bb )
    {
        switch( f )
        {
            case 0: OR( rt, opn ); break;
            case 1: ADD( rt, opn ); break;
            case 2: XOR( rt, opn ); break;
        }
        return;
    }
    pushDown( rt );
    int mid = ( l + r ) / 2;
    int ls = 2 * rt; int rs = ls | 1;
    if( mid >= aa ) update( l, mid, ls, aa, bb, opn, f );
    if( mid < bb ) update( mid + 1, r, rs, aa, bb, opn, f );
    pushUp( rt );
}

int main()
{
    int t, n, m, aa, bb, opn; char cmd[4];
    scanf("%d", &t);
    while( t-- )
    {
        memset( flag, -1, sizeof(flag) );
        scanf("%d%d", &n, &m);
        build(0, n-1, 1);
        while( m-- )
        {
            scanf("%s", cmd);
            if( cmd[0] == 'S' )
            {
                scanf("%d%d", &aa, &bb);
                res = 0;
                query( 0, n - 1, 1, aa, bb );
                printf("%d\n", res);
            }
            else
            {
                scanf("%d%d%d", &opn, &aa, &bb);
                switch( cmd[0] )
                {
                    case 'O': update(0, n-1, 1, aa, bb, opn, 0); break;
                    case 'A': update(0, n-1, 1, aa, bb, opn, 1); break;
                    case 'X': update(0, n-1, 1, aa, bb, opn, 2); break;
                    default : break;
                }
            }
        }
    }
    return 0;
}

 

posted on 2013-11-20 21:40  细雨微光  阅读(290)  评论(0)    收藏  举报