题目链接
题目分析:
见(lyd)书(0x59)单调队列优化(DP)
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<ctime>
#include<queue>
#define N (20000 + 5)
#define M (100 + 5)
using namespace std;
inline int read() {
int cnt = 0, f = 1; char c = getchar();
while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + (c ^ 48); c = getchar();}
return cnt * f;
}
int n, m, f[M][N];
int q[N], head, tail, pos[N];
struct node {
int l, p, s;
}a[M];
bool cmp(node a, node b) {return a.s < b.s;}
int calc(int i, int k) {
return f[i - 1][k] - a[i].p * k;
}
int main() {
n = read(), m = read();
for (register int i = 1; i <= m; ++i) a[i].l = read(), a[i].p = read(), a[i].s = read();
sort (a + 1, a + m + 1, cmp);
for (register int i = 1; i <= m; ++i) {
head = 1, tail = 0;
for (register int j = max(0, a[i].s - a[i].l); j <= a[i].s - 1; ++j) {
while (head <= tail && calc(i, q[tail]) <= calc(i, j)) --tail;
q[++tail] = j;
}
for (register int j = 1; j <= n; ++j) {
f[i][j] = max(f[i][j - 1], f[i - 1][j]);
if (j < a[i].s) continue;
while (head <= tail && q[head] < j - a[i].l) ++head;
if (head <= tail) f[i][j] = max(f[i][j], calc(i, q[head]) + a[i].p * j);
}
}
printf("%d", f[m][n]);
return 0;
}