链接:https://www.nowcoder.net/acm/contest/78/D
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
常州大学组织了新生寒假训练一共N天,每天训练可以获得的训练效果是Ei。但是如果连续训练超过K天,萌新们会受不了而被劝退。
现在负责人想知道,如何安排能保证萌新不会被劝退并且能获得最大的训练效果。
输入描述:
第一行:两个用空格隔开的整数:N和K,1≤N≤100000,1≤K≤N
第二行到N+1行:第i+1行有一个整数,表示第N天的训练效果是Ei,(0 <= Ei <= 1,000,000,000)
输出描述:
第一行:单个整数,表示最大的能力之和
示例1
输入
5 2 1 2 3 4 5
输出
12
说明
(除了第三天以外每天都在训练,总训练效果为1+2+4+5=12)
备注:
1≤n≤100,000
思路:dp[i]存一下在第i天休息时前i天最少未获得多少能量。这样dp[i] = min(dp[j]) + a[i], j从i - k到i - 1。此时复杂度O(n*k)。发现可以单调队列优化,最后时间复杂度O(n)。
#include <iostream> #include <fstream> #include <sstream> #include <cstdlib> #include <cstdio> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <queue> #include <stack> #include <vector> #include <set> #include <map> #include <list> #include <iomanip> #include <cctype> #include <cassert> #include <bitset> #include <ctime> using namespace std; #define pau system("pause") #define ll long long #define pii pair<int, int> #define pb push_back #define mp make_pair #define clr(a, x) memset(a, x, sizeof(a)) const double pi = acos(-1.0); const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const double EPS = 1e-9; int n, k; ll a[100015], dp[100015], ans; deque<int> que; int main() { scanf("%d%d", &n, &k); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); ans += a[i]; } que.pb(0); for (int i = 1; i <= n; ++i) { if (que.front() + k + 1 < i) { que.pop_front(); } int x = que.front(); dp[i] = dp[x] + a[i]; while (que.size()) { int y = que.back(); if (dp[y] >= dp[i]) { que.pop_back(); } else { break; } } que.pb(i); } ll mi = 1e18; for (int i = max(n - k, 1); i <= n; ++i) { mi = min(dp[i], mi); } printf("%lld ", ans - mi); return 0; }