• 【洛谷P2034】选择数字


    Description

    【洛谷P2034】选择数字

    给定一个序列,选择其中若干个数,但不能有超过k个连续的数字被选择。最大化选出的数字之和。

    Solution

    dp+单调队列

    正难则反,考虑从序列中取出一些数,这些数两两之间的距离不超过k,最小化之和

    那么定义$f[i]$表示前i个数,取出一些的最小和(保证第i个取),那么显然有状态转移方程

    $$f[i]=min{f[j]}+a[i]quad (i-k-1le j<i)$$

    可以发现,对于每一个i,决策允许集合中的j都是连续的一段,并且当i增加时,决策允许集合会与之前的一部分重叠,而且转移是求出最值,所以用一个单调队列维护一下就好了、

    时间复杂度为$O(n)$

    Code

    #include <bits/stdc++.h>
    // check if it is judged online
    
    namespace shl {
        typedef long long ll;
        inline int read() {
            int ret = 0, op = 1;
            char c = getchar();
            while (!isdigit(c)) {
                if (c == '-') op = -1;
                c = getchar();
            }
            while (isdigit(c)) {
                ret = ret * 10 + c - '0';
                c = getchar();
            }
            return ret * op;
        }
        int n, m;
        ll a[100010], sum, f[100010], que[100010], h = 1, t = 1, tot;
        int main() {
            n = read(), m = read();
            for (register int i = 1; i <= n; ++i) a[i] = read(), tot += a[i];
            for (register int i = 1; i <= n; ++i) {
                f[i] = f[que[h]] + a[i];
                while (h <= t && f[i] <= f[que[t]]) t--;
                que[++t] = i;
                while (h <= t && que[h] <= i - m - 1) h++;
            }
            ll ans = 0;
            for (register int i = n - m; i <= n; ++i) ans = std::max(ans, tot - f[i]);
            printf("%lld
    ", ans);
            return 0;
        }
    }
    int main() {
    #ifdef LOCAL
        freopen("textname.in", "r", stdin);
        freopen("textname.out", "w", stdout);
    #endif
        shl::main();
        return 0;
    }
  • 相关阅读:
    4、springboot之全局异常捕获
    3、springboot之热部署
    可重入锁
    2、springboot返回json
    1、springboot之HelloWorld
    [转]查询 SQL Server 系统目录常见问题
    设计模式原则详解
    [转]第二章 控制反转和依赖注入
    [转]Spring.Net介绍
    [转]Oracle High Water Level高水位分析
  • 原文地址:https://www.cnblogs.com/shl-blog/p/11520354.html
Copyright © 2020-2023  润新知