• [BZOJ 2151]种树


    Description

    题库链接

    给你一个长度为 (n) 的环状序列,每一个位置有一定权值,让你选出恰好 (m) 个位置,使得选出的位置两两不相邻并且权值和最大。求最大权值和。

    (1leq nleq 200000)

    Solution

    [APIO/CTSC 2007]数据备份有点类似。

    (g(x)) 为恰好选 (x) 个位置时,最大的权值和。可以发现 (g(x)) 是上凸的。因此考虑带权二分。二分上下界取位置上的权值最值。

    (f_{i,1/0,1/0}) 为第一个位置选或不选,第 (i) 个位置选或不选获得的最大权值和。DP 只需考虑 (i)(i-1) 这两个位置选取与否。

    对于 (g) 函数可能存在相邻若干点斜率相同的情况,还是和上一题一样的做法,转移时记录最少选点数。之后每次二分到选点数 (leq m) 的值时更新答案。

    Code

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 200000+5, inf = 1e9;
    
    int n, m, f[N][2][2], a[N], g[N][2][2], tmp;
    
    bool check(int mid) {
        f[1][1][1] = a[1]-mid, g[1][1][1] = 1;
        f[1][0][0] = 0, g[1][0][0] = 0;
        f[1][1][0] = f[1][0][1] = -inf;
        for (int i = 2; i <= n; i++)
            for (int j = 0; j <= 1; j++) {
                f[i][j][1] = f[i-1][j][0]+a[i]-mid;
                g[i][j][1] = g[i-1][j][0]+1;
                if (f[i-1][j][0] > f[i-1][j][1] || (f[i-1][j][0] == f[i-1][j][1] && g[i-1][j][0] < g[i-1][j][1]))
                    f[i][j][0] = f[i-1][j][0], g[i][j][0] = g[i-1][j][0];
                else f[i][j][0] = f[i-1][j][1], g[i][j][0] = g[i-1][j][1];
            }
        int mf = -inf, mg = 0;
        for (int i = 0; i <= 1; i++)
            for (int j = 0; j <= 1; j++)
                if (!(i&j))
                    if (f[n][i][j] > mf || (f[n][i][j] == mf && g[n][i][j] < mg))
                        mf = f[n][i][j], mg = g[n][i][j];
        tmp = mf+m*mid;
        return mg <= m;
    }
    int main() {
        scanf("%d%d", &n, &m);
        if (n/2 < m) {puts("Error!"); return 0; }
        for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
        int l = -1000, r = 1000, ans = -1, mid;
        while (l <= r) {
            mid = (l+r)>>1;
            if (check(mid)) r = mid-1, ans = tmp;
            else l = mid+1;
        }
        printf("%d
    ", ans);
        return 0;
    }
  • 相关阅读:
    【linux】系统初始化的shell脚本
    【mysql】数据库Schema的优化
    【mysql】使用xtrabackup在线增量备份及恢复数据库
    mysql中日志的配置与分析
    Javascript 计算字符串所占字节数
    Javascript调试利器console的使用
    Javascript中类型的判断
    Javascript中的数据类型知多少
    Javascript中bind()方法的使用与实现
    【mysql】Innodb三大特性之insert buffer
  • 原文地址:https://www.cnblogs.com/NaVi-Awson/p/13515254.html
Copyright © 2020-2023  润新知