Hacker, pack your bags! Codeforces Round #422 (Div. 2) (贪心)

题目链接

http://codeforces.com/contest/822/problem/C

题目大意

给你n个时间段,有起始日期和结束日期,用int型书表示,还有一个目标天数x, 每个时间段有一个cost值,问你从n个时间段取出两个时间段持续时间加起来正好为x,且1.cost总和最小, 2.时间段不能重叠,即ri < lj 或 rj < li;

核心思想

首先要想到可以用一个best[i]数组去记录i长度所需花费的最小cost,我们需要根据输入数据不断地去更新它,使他成立;

我们定义一个结构体P{int p, int len, int cost, int type}pp[M];
p 表示起始日期或结束日期, len表示这个时间段的长度,type则用来标记该时间点是起始日期还是结束日期

我们把pp[M]数组按照p的大小排序, 如果p相同,那么再看type,我们要使结束日期排在起始日期的后面(为什么不能反过来呢?如果碰到起始日期节点更新best数组, 那么我们碰到结束日期节点更新ans时就可能把重叠的时间段算进去了(两段时间段其中一个终点和另一个起点重叠时),这个是本题的关键一定要理解)。这样所有时间段就按照时间点的先后排好序了,我们就可以开始更新答案了

把所有数据扫一遍,如果遇到一个结束日期节点,那么我们就要更新best[i], best[pp[i].len] = min(best[pp[i].len], pp[i].cost);
如果碰到一个起始日期节点,那么我们就要更新ans,
ans = min(ans, pp[i].cost + best[x - pp[i].len]);

代码

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
const int M = 2e5 + 5;
const int INF = 2e9 + 7;
int a[M], best[M];

struct P
{
    int p, len, cost, type;
        bool operator < (const P&a)
        {
            if(p == a.p) return type > a.type;
            return p < a.p;
        }
}pp[2*M];

int main()
{
        int n, x, top = 0;
        scanf("%d%d", &n, &x);
        for(int i=0; i<n; ++i)
        {
                int l, r, cst;
                scanf("%d%d%d", &l, &r, &cst);
                pp[top++] = P{l, r - l + 1, cst, 1};
                pp[top++] = P{r, r - l + 1, cst, -1};
        }
        ll ans = INF;
        sort(pp, pp+top);
        fill(best, best+x, INF);

        for(int i=0; i<top; ++i)
        {
            if(pp[i].len >= x) continue;
            if(pp[i].type == 1)
            {
                ans = min(ans, (ll)pp[i].cost + (ll)best[x - pp[i].len]);
            }
            else best[pp[i].len] = min(best[pp[i].len], pp[i].cost);
        }
    if(ans == INF) ans = -1;
    cout<<ans<<endl;
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值