zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    webpack.DefinePlugin
    webpack-dev-server配置指南(使用webpack3.0)
    Eclipse配色方案插件
    解决Sublime Text 3中文显示乱码问题(转)
    Java连接SqlServer2008数据库
    [转]java中判断字符串是否为数字的三种方法
    VS2008 SP1 安装卡在 VS90sp1-KB945140-X86-CHS的解决方法
    Python获取桌面路径
    关于fdisk命令
    socket 错误之:OSError: [WinError 10057] 由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。
  • 原文地址:https://www.cnblogs.com/GBRgbr/p/3292478.html
Copyright © 2011-2022 走看看