[CodeForces555B]Case of Fugitive[贪心][优先队列]

来源:互联网 发布:南华大学核专业知乎 编辑:程序博客网 时间:2024/04/27 22:15

题目链接:[CodeForces555B]Case of Fugitive[贪心][优先队列]

题意分析:依次排列成行的岛屿间需要假设桥梁,问:是否能在岛间都搭上桥?能,输出每个隔间需要的桥号。否则,输出"No"。

解题思路:贪心。按桥的长度升序排列,按岛屿间的最短距离island[i + 1].l - island[i].r升序排序。每次记录当前桥能搭上的岛屿数,然后把桥搭在这些岛屿中,岛屿间距离island[i + 1].r - island[i].l最小的那个上。
下面小小证明下这个贪心思路:当当前桥能搭上这些岛屿时,说明后面的桥都能满足大于这些岛屿最小间隔,但是不一定满足这些岛屿最大间隔的最小值。所以每次取出时我们尽量去选择最大间隔小的去放,这样就能使后期最大间隔的最小值变大。

个人感受:贪心贪心,多思考,多思考TAT

具体代码如下:

#include <iostream>#include <cstdio>#include <queue>#include <vector>#include <cstring>#include <string>#include <cmath>#include <map>#include <set>#include <algorithm>typedef long long ll;using namespace std;const int MAXN = 2e5 + 111;struct Island{    int id;    ll l, r;    bool operator < (const Island& t)const{        return r > t.r;    }}island[MAXN];bool cmp(const Island& a, const Island& b){    return a.l < b.l;}struct B{    ll len;    int id;    bool operator < (const B& t)const{        return len < t.len;    }}b[MAXN];int ans[MAXN];int main() {    int n, m;    scanf("%d %d", &n, &m);    for (int i = 1; i <= n; ++i)        scanf("%lld %lld", &island[i].l, &island[i].r);    for (int i = 1; i <= n - 1; ++i) //循环利用数组,将岛屿的左右转换为岛屿间的最小间隔与最大间隔~    {        ll mi = island[i + 1].l - island[i].r, mx = island[i + 1].r - island[i].l;        island[i].l = mi, island[i].r = mx;        island[i].id = i;    }    for (int i = 1; i <= m; ++i)    {        scanf("%lld", &b[i].len);        b[i].id = i;    }    sort(island + 1, island + n, cmp);    sort(b + 1, b + m + 1);    priority_queue<Island> q;    int cnt = 1, num = 0;    for (int i = 1; i <= m; ++i)    {        while (!q.empty() && q.top().r < b[i].len) //如果比当前桥长度都小,那么肯定比后面桥还短            q.pop();        while (cnt <= n - 1 && island[cnt].l <= b[i].len && b[i].len <= island[cnt].r) //能在岛间搭桥            q.push(island[cnt++]);        if (q.empty())            continue;        Island tem = q.top(); q.pop(); //取出能搭桥的岛中,r最小的        ans[tem.id] = b[i].id;        ++num;    }    if (num == n - 1)    {        printf("Yes\n");        for (int i = 1; i < n - 1; ++i)            printf("%d ", ans[i]);        printf("%d\n", ans[n - 1]);    }    else puts("No");    return 0;}

0 0