zoukankan      html  css  js  c++  java
  • [APIO/CTSC 2007]数据备份

    Description

    题库链接

    数轴上有 (n) 个点,让你选出恰好 (k) 对互异的点对,最小化所有点对间的距离和。

    (1leq 2kleq nleq 100000)

    Solution

    首先一个显然的贪心是每个点对一定都是相邻的点。

    (f_{i, j, 1/0}) 表示前 (i) 个点中,选出 (j) 个点对,第 (i) 个点是/否被选的最小距离和。转移就考虑第 (i) 个点和第 (i-1) 个点是否组成点对。

    这是一个 (O(nk)) 的 DP。不过考虑 (g(x)) 表示恰好选 (x) 个点对时的最小距离和,可以证明 (g) 是下凸的。因此可以带权二分优化。二分后的 DP 可以直接去掉第二维,每连接一个点对就减去二分的权值。只不过要开一个辅助数组记录连了几个点对。

    当然有时候会有二分不到目标点的情况。这是因为目标点与相邻的点共线。那么可以做如下的处理:当 (f) 值相等时,取最少的连线对数。那么当前二分的权值算出的点对数 (leq k) 时,就对答案进行一次更新:(f+k imes mid)。由于凸函数性质,如果这一算式是错解那么它一定不会成为最终的答案,因此不会有误算的情况。

    二分上下界:下界取 (0),此时一个点对都不取最优;上界取坐标的最大值,因为每次连边的代价为负,因此所有点都选上最优。

    Code

    #include <bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N = 100000+5;
    const ll inf = 1e16;
    
    int n, k, g[N][2], a[N];
    ll f[N][2], tmp;
    
    bool check(ll m) {
        f[1][0] = g[1][0] = 0;
        f[1][1] = inf;
        for (int i = 2; i <= n; i++) {
            f[i][0] = f[i-1][0], g[i][0] = g[i-1][0];
            if (f[i-1][1] < f[i][0] || (f[i-1][1] == f[1][0] && g[i-1][1] < g[i][0]))
                f[i][0] = f[i-1][1], g[i][0] = g[i-1][1];
            f[i][1] = f[i-1][0]+a[i]-a[i-1]+m, g[i][1] = g[i-1][0]+1;
        }
        ll mf, mg;
        mf = f[n][f[n][1] < f[n][0] || (f[n][1] == f[n][0] && g[n][1] < g[n][0])];
        mg = g[n][f[n][1] < f[n][0] || (f[n][1] == f[n][0] && g[n][1] < g[n][0])];
        if (mg <= k) return tmp = mf-m*k, true;
        return false;
    }
    int main() {
        scanf("%d%d", &n, &k);
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        int l = -1e9, r = 0, mid; ll ans = -1;
        while (l <= r) {
            mid = (l+r)>>1;
            if (check(mid)) r = mid-1, ans = tmp;
            else l = mid+1;
        }
        printf("%lld
    ", ans);
        return 0;
    }
  • 相关阅读:
    软件工程--团队作业3
    软件工程--团队作业2
    软件工程第二次作业---结对编程
    软件工程第一次作业补充
    软件工程第一次作业
    用Use Case获取需求的方法是否有什么缺陷,还有什么地方需要改进?
    买卖股票的最佳时机
    爬楼梯
    删除排序数组中的重复数字
    1500802035王叔文
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/13503681.html
Copyright © 2011-2022 走看看