有N块木板从左到右排成一行,有M个工匠对这些木板进行粉刷,每块木板至多被粉刷一次。
第 i 个木匠要么不粉刷,要么粉刷包含木板 Si 的,长度不超过 Li 的连续的一段木板,每粉刷一块可以得到 Pi 的报酬。
不同工匠的Si不同。
请问如何安排能使工匠们获得的总报酬最多。
输入格式
第一行包含两个整数N和M。
接下来M行,每行包含三个整数Li,Pi,Si。
输出格式
输出一个整数,表示结果。
数据范围
1≤N≤16000,
1≤M≤100,
1≤Pi≤10000
输入样例:
8 4
3 2 2
3 2 3
3 3 5
1 1 7
输出样例:
17
#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
using namespace std;
const int N = 16e3 + 10, M = 105;
int f[M][N];
struct rec {
int l, p, s;
bool operator<(const rec w) const {
return s < w.s;
}
} a[M];
int n, m;
deque<pii > q;
inline int calc(int i, int k) {
return f[i - 1][k] - k * a[i].p;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++)
scanf("%d%d%d", &a[i].l, &a[i].p, &a[i].s);
sort(a + 1, a + 1 + m);
for (int i = 1; i <= m; i++) {
q.clear();
for (int k = max(0, a[i].s - a[i].l); k <= a[i].s - 1; k++) {
int res = calc(i, k);
while (!q.empty() && q.back().se <= res)q.pop_back();
q.emplace_back(k, res);
}
for (int j = 1; j <= n; j++) {
f[i][j] = max(f[i][j - 1], f[i - 1][j]);
if (j >= a[i].s && j <= min(a[i].s + a[i].l - 1, n)) {
while (!q.empty() && q.front().fi < j - a[i].l)q.pop_front();
if (!q.empty())f[i][j] = max(f[i][j], q.front().se + a[i].p * j);
}
}
}
printf("%d\n", f[m][n]);
return 0;
}