• 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
    ", sum );
            }
        }
        return 0;
    }
  • 相关阅读:
    [转]VC++下使用ADO操作数据库
    VC++ GetSafeHwnd()和GetSafeHandle()
    VC++ GetSafeHwnd用法
    C++中的const成员函数(函数声明后加const,或称常量成员函数)用法详解
    VC++ Debug条件断点使用
    VC++为你的程序增加内存泄露检测
    VC++ Debug格式化数值显示
    VC++Debug查看堆对象内容,即使符号已经超出作用范围
    VC++ Debug产生异常时中断程序执行Break on Exception
    一个简单的伪随机数发生算法
  • 原文地址:https://www.cnblogs.com/GBRgbr/p/3292478.html
Copyright © 2020-2023  润新知