题意:头牛,每头牛在到时间段干活并需要数量的钱,想要在到时间段的每一时刻都有牛在干活,最少需要多少钱?
思路:首先把不在到时间段干活的牛给去除,在把剩下的牛按照从小到大排序,表示从到都有牛干活的最下花费,挨个遍历每个时间段,有:
其中找最小值部分可以用线段树来优化
#include
#include
#include
#define lson num << 1
#define rson num << 1 | 1
#define maxn 90005
#define maxm 10007
#define INF 0x3f3f3f3f
using namespace std;
struct node
{
int l,r,Min;
}tree[maxn << 2];
int s[maxm],t[maxm];
struct _node
{
int l,r,S;
}p[maxm];
bool cmp(struct _node a,struct _node b)
{
if(a.r == b.r)
return a.l < b.l;
else return a.r < b.r;
}
void build(int num,int l,int r)
{
tree[num].l = l;
tree[num].r = r;
tree[num].Min = INF;
if(l == r)
return;
int mid = (l + r) >> 1;
build(lson,l,mid);
build(rson,mid + 1,r);
}
void update(int num,int pos,int val)
{
if(tree[num].l == tree[num].r && pos == tree[num].l) {
tree[num].Min = val;
return;
}
int mid = (tree[num].l + tree[num].r) >> 1;
if(pos <= mid)
update(lson,pos,val);
else
update(rson,pos,val);
tree[num].Min = min(tree[lson].Min,tree[rson].Min);
}
int query(int num,int l,int r)
{
int res;
if(tree[num].l == l && tree[num].r == r)
return tree[num].Min;
int mid = (tree[num].l + tree[num].r) >> 1;
res = INF;
if(r <= mid)
res = min(res,query(lson,l,r));
else if(l > mid)
res = min(res,query(rson,l,r));
else {
res = min(res,query(lson,l,mid));
res = min(res,query(rson,mid + 1,r));
}
return res;
}
int main(void)
{
int l,r,i,n,M,E,cnt,L,R,S,t,ans;
scanf("%d %d %d",&n,&M,&E);
cnt = 0;
L = INF;
R = -1;
for(i = 0; i < n; i++) {
scanf("%d %d %d",&l,&r,&S);
if(r < M || l > E) continue;
L = min(L,l);
R = max(R,r);
p[cnt].l = l;
p[cnt].r = r;
p[cnt].S = S;
cnt++;
}
L--;
build(1,L,R);
update(1,M - 1,0);
sort(p,p + cnt,cmp);
for(i = 0; i < cnt; i++) {
t = query(1,p[i].r,p[i].r);
ans = query(1,p[i].l - 1,p[i].r - 1) + p[i].S;
if(t > ans)
update(1,p[i].r,ans);
}
ans = query(1,E,R);
if(ans == INF)
printf("-1\n");
else
printf("%d\n",ans);
return 0;
}