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;
    }
  • 相关阅读:
    C#编程思路
    将字符串类型字段转为map类型字段,使用str_to_map()函数
    写hive脚本时,如果hive的过滤条件比较多。可以把过滤条件放到一个参数里。然后把参数放到过滤条件处。这样以后只需要改参数就可以了
    linux中. 路径/文件
    inner join ,left join 会导致数据发散
    如何批量按分区插入数据
    hive表添加字段后,查不出数据是咋回事?
    linux中$0的含义
    linux中的$#含义
    linux的语法
  • 原文地址:https://www.cnblogs.com/GBRgbr/p/3292478.html
Copyright © 2011-2022 走看看