思路:
设f[i][j]表示到第i个人,涂前j个
所以
f
[
i
]
[
j
]
=
m
a
x
(
f
[
i
−
1
]
[
k
]
+
(
j
−
k
)
∗
p
[
i
]
)
f[i][j]=max(f[i-1][k]+(j-k)*p[i])
f[i][j]=max(f[i−1][k]+(j−k)∗p[i])
用单调队列滚掉
f
[
i
−
1
]
[
k
]
−
k
∗
p
[
i
]
f[i-1][k]-k*p[i]
f[i−1][k]−k∗p[i]
然后滚动数组滚掉i
c o d e code code
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n, m, f[101010], x[101010], q[101010], w[101010];
struct node
{
int p, l, s;
}a[101010];
bool cmp(node x, node y)
{
return x.s<y.s;
}
int main()
{
scanf("%d%d", &m, &n);
for(int i=1; i<=n; i++)
scanf("%d%d%d", &a[i].l, &a[i].p, &a[i].s);
sort(a+1, a+1+n, cmp);
for(int i=1; i<=n; i++)
{
int left=max(0, a[i].s-a[i].l), right=min(m, a[i].s+a[i].l);
for(int j=left; j<=right; j++)
x[j]=f[j]-a[i].p*j;
int hd=1, tl=0;
for(int j=left; j<a[i].s; j++)
{
while(hd<=tl&&q[tl]<=x[j]) tl--;
q[++tl]=x[j];
w[tl]=j;
}
for(int j=a[i].s; j<=right; j++)
{
while(hd<=tl&&w[hd]<j-a[i].l) hd++;
if(hd>tl)
break;
f[j]=max(f[j], q[hd]+a[i].p*j);
}
for(int j=2; j<=m; j++)
f[j]=max(f[j], f[j-1]);
}
printf("%d", f[m]);
return 0;
}