• 「BZOJ 1831」「AHOI 2008」逆序对「贪心」


    题意

    给定一个长度为(n),值域为([1,k]),某些位置不确定的数组,求最小的逆序对。(nleq 10^4, k leq 100)

    题解

    这题有人用前缀和优化(dp)过了,但是这里还是讲一种逐一填的做法

    首先证明:填进去的数一定是单调不减的,换句话说不构成逆序对。证明很简单,因为假设在(i)(j)两处((i < j)),填进去的数构成逆序对,交换这(i, j),不影响([1, i - 1],[j + 1, n])的逆序对,对于([i + 1, j - 1])来说逆序对减少或不变,并且(i,j)构成的逆序对消失。

    所以我们只要考虑已经填好的数。每次找到一个贡献最小的(k)填就行了。

    我用树状数组维护了一下,实际上直接数组也可以。

    #include <algorithm>
    #include <cstdio>
    using namespace std;
    
    const int N = 1e4 + 10;
    
    int n, k, a[N], bit[2][N];
    
    void add(int z, int x, int y) {
        for(; x <= k; x += x & (-x)) bit[z][x] += y;
    }
    int qry(int z, int x) {
        int ans = 0;
        for(; x >= 1; x &= x - 1) ans += bit[z][x];
        return ans;
    }
    
    int main() {
        scanf("%d%d", &n, &k);
        for(int i = 1; i <= n; i ++) {
            scanf("%d", a + i);
            if(~ a[i]) add(1, a[i], 1);
        }
        int ans = 0;
        for(int i = 1; i <= n; i ++) {
            if(a[i] == -1) {
                int x = 1, y = n << 1;
                for(int j = 1; j <= k; j ++) {
                    int s = qry(0, k) - qry(0, j) + qry(1, j - 1);
                    if(s < y) y = s, x = j;
                }
                a[i] = x;
                add(0, a[i], 1);
            } else add(0, a[i], 1), add(1, a[i], -1);
            ans += qry(0, k) - qry(0, a[i]);
        }
        printf("%d
    ", ans);
        return 0;
    }
    
    
  • 相关阅读:
    weka 文本分类(1)
    python 笔记1
    PAT乙级 1028. 人口普查(20)
    PAT乙级 1027. 打印沙漏(20)
    PAT乙级 1026. 程序运行时间(15)
    Eclipse常用快捷键
    MyBatis源码分析(各组件关系+底层原理
    springmvc异常处理
    Elasticsearch学习(一)————简单命令
    mybatis传入参数类型parameterType详解
  • 原文地址:https://www.cnblogs.com/hongzy/p/10357877.html
Copyright © 2020-2023  润新知