Description
A team of
K(1<=K<=100)
workers should paint a fence which contains
N(1<=N<=16000)
planks numbered from 1 to
N
from left to right. Each worker
Being the team’s leader you want to determine for each worker the interval that he should paint, knowing that the total income should be maximal. The total income represents the sum of the workers personal income.
Write a program that determines the total maximal income obtained by the
K
workers.
Input
The input contains:
L2
P2
S2
...
LK
PK
SK
Semnification
N
-the number of the planks;
Li
-the maximal number of planks that can be painted by worker
i
Output
The output contains a single integer, the total maximal income.
Sample Input
8 4
3 2 2
3 2 3
3 3 5
1 1 7
Sample Output
17
Hint
Explanation of the sample:
the worker 1 paints the interval [1, 2];
the worker 2 paints the interval [3, 4];
the worker 3 paints the interval [5, 7];
the worker 4 does not paint any plank
Source
Romania OI 2002
思路
单调队列优化dp。
令
再用单调队列优(luan)化(gao)就AC了。
代码
#include <cstdio>
#include <algorithm>
const int maxk=100;
const int maxn=16000;
struct data
{
int l,p,s;
bool operator <(const data &other) const
{
return s<other.s;
}
};
int f[maxk+10][maxn+10];
int n,k;
data d[maxk+10];
int q[maxn+10],head,tail;
int main()
{
scanf("%d%d",&n,&k);
for(int i=1; i<=k; i++)
{
scanf("%d%d%d",&d[i].l,&d[i].p,&d[i].s);
}
std::sort(d+1,d+k+1);
for(int i=1; i<=k; i++)
{
head=0;
tail=1;
q[1]=0;
for(int j=1; j<d[i].s; j++)
{
f[i][j]=std::max(f[i][j-1],f[i-1][j]);
while((head!=tail)&&(f[i-1][q[tail]]-q[tail]*d[i].p<f[i-1][j]-j*d[i].p))
{
tail--;
}
tail++;
q[tail]=j;
}
for(int j=std::max(1,d[i].s); j<=n; j++)
{
f[i][j]=std::max(f[i][j-1],f[i-1][j]);
if(d[i].s<=j-d[i].l)
{
continue;
}
while((head!=tail)&&(q[head]<j-d[i].l))
{
head++;
}
f[i][j]=std::max(f[i][j],f[i-1][q[head]]-q[head]*d[i].p+j*d[i].p);
}
}
printf("%d\n",f[k][n]);
return 0;
}