HDU 3854 Glorious Array 树状数组

一组数据:

2
9 10 2
2 3 1 4 2 5 1 3 4
0 1 0 1 1 1 1 1 0
1
0 4
1
0 4
1
0 5
0 7
1
0 2
1
5 10 2
1 1 1 1 1
0 1 0 1 0
1
0 3
1
0 3
1
0 1
0 4
0 5
0 2
1

答案:

16
16
16
16
15
6
6
6
6

以第一组为例:

2 3 1 4 2 5 1 3 4

以小于K的数为分界,将数列分成几段。

对于每个数字,记录它所在段的左端点和右端点,据此求出修改前的合法对数sum。

对于每个修改,查看当前修改发生在哪一段,该修改对sum产生了怎样的影响,修改sum即可。

树状数组C[i]记录区间[1, i]共有多少个白点。

注意修改发生在段内和段端点处要分开考虑。

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <algorithm>



#define LL long long int



using namespace std;



const int MAXN = 100100;



int N, Q, K;

int C[MAXN];         //1-i之间有多少个白点

int val[MAXN];

int left[MAXN];

int right[MAXN];

LL sum;

bool color[MAXN];



int lowbit( int x )

{

    return x & (-x);

}



void Update( int x, int val )

{

    while ( x <= N )

    {

        C[x] += val;

        x += lowbit(x);

    }

    return;

}



int Query( int x )

{

    if ( x == 0 ) return 0;

    int res = 0;

    while ( x > 0 )

    {

        res += C[x];

        x -= lowbit(x);

    }

    return res;

}



void init()

{

    int pre = 0;

    for ( int i = 1; i <= N; ++i )

    {

        left[i] = pre;

        if ( val[i] < K )

            pre = i;

    }



    pre = N + 1;

    for ( int i = N; i > 0; --i )

    {

        if ( val[i] < K )

            pre = i;

        right[i] = pre;

    }

    return;

}



int main()

{

    //freopen( "in.txt", "r", stdin );

    int T;

    scanf( "%d", &T );

    while ( T-- )

    {

        memset( C, 0, sizeof(C) );

        scanf( "%d%d%d", &N, &Q, &K );



        for ( int i = 1; i <= N; ++i )

            scanf("%d", &val[i] );



        for ( int i = 1; i <= N; ++i )

        {

            int a;

            scanf("%d", &a );

            if ( a == 0 )

            {

                Update( i, 1 );

                color[i] = true;

            }

            else color[i] = false;

        }

        init();



        sum = 0;

        for ( int i = 1; i <= N; ++i )

        if ( val[i] < K )

        {

            LL white = Query(i) - Query( left[i] );

            LL black = i - left[i] - white;

            LL houW = Query(N) - Query(i - 1);

            LL houB = N - i + 1 - houW;

            sum += white * houB + black * houW;

        }



        for ( int i = 0; i < Q; ++i )

        {

            int op;

            scanf( "%d", &op );

            if ( op == 0 )

            {

                int v;

                scanf( "%d", &v );



                LL preW, preB, aftW, aftB;

                if ( val[v] >= K )

                {

                    preW = Query( left[v] );

                    preB = left[v] - preW;

                    aftW = Query(N) - Query( right[v] - 1 );

                    aftB = N - right[v] + 1 - aftW;

                }

                else

                {

                    preW = Query( v - 1 );

                    preB = v - 1 - preW;

                    aftW = Query(N) - Query(v);

                    aftB = N - v - aftW;

                }



                if ( color[v] )  //之前是白的

                {

                    sum = sum - preB - aftB + preW + aftW;

                    Update( v, -1 );

                }

                else             //之前是黑的

                {

                    sum =  sum + preB + aftB - preW - aftW;

                    Update( v, 1 );

                }

                color[v] = !color[v];

            }

            else

                printf( "%I64d\n", sum );

        }

    }

    return 0;

}

 

你可能感兴趣的:(array)