Codeforces 721E DP
Posted pkgunboat
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 721E DP相关的知识,希望对你有一定的参考价值。
大概思路及题意看这篇博客吧
我的理解:设f[i]表示处理到第i个区间,能唱的最多的歌,g[i]是保证f[i]最大时最靠左的点。那么f[i] = max(f[j] + (r[i] - max(l[i], g[j] + t)) / p), g[i] = r[i] - (r[i] - max(l[i], g[j] + t)) % p);容易发现, f[i]和g[i]是单增的,所以有很多状态是不可能转移的。只有在两个位置之间的状态才有可能更新状态。1:g[j] + t <= [i]的最大的j。2:g[j] + t <= r[i]的最大的j。在这之间的状态有可能会对状态产生影响,我们需要一个个出队,去更新状态,这样有很多的状态出队了,大大降低了时间复杂度。需要注意,第二个位置的状态在出队之后还需要入队,因为它可能成为i + 1状态的1位置。
代码:
#include <bits/stdc++.h> #define pii pair<int, int> using namespace std; const int maxn = 100010; int f[maxn], g[maxn]; int q[maxn]; pii a[maxn]; int main() { int L, n, p, t; scanf("%d%d%d%d", &L, &n, &p, &t); for (int i = 1; i <= n; i++) scanf("%d%d", &a[i].first, &a[i].second); int l = 1, r = 0; g[0] = -t; for (int i = 1; i <= n; i++) { f[i] = f[i - 1]; g[i] = g[i - 1]; l--; while(l <= r && g[q[l]] + t <= a[i].second) { int x = max(a[i].first, g[q[l]] + t); int y = f[q[l]] + (a[i].second - x) / p; int z = a[i].second - (a[i].second - x) % p; if(y > f[i] || (y == f[i] && g[i] > z)) { f[i] = y; g[i] = z; } l++; } q[++r] = i; } printf("%d\\n", f[n]); }
以上是关于Codeforces 721E DP的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 86C Genetic engineering(AC自动机+DP)
CodeForces 1005D Polycarp and Div 3(思维贪心dp)
Codeforces Round #267 (Div. 2) C. George and Job
代码源 Div1#104no crossing,Codeforces 793D,2100分,区间dp
[Codeforces Round #522 (Div. 2, based on Technocup 2019 Elimination Round 3)][C. Playing Piano](代码片段