Codeforces 555B - Case of Fugitive 搭桥

题意:给出n段路和m座桥。每段路的两个端点一维坐标表示。要从m座桥中选出一些桥搭在每两条相邻的路上,使得这些路全部连通。每两条相邻的路之间只能搭一座桥,且桥的两端必须恰好分别落在两段路上。如果存在一种搭桥方法,则输出Yes并按题目给定的路形成的空隙的顺序输出每座桥的序号,若不能则输出No。

题意换个说法实际上就是给定n - 1个区间和m个数,问是否能从m个数中选出n - 1个数,恰好分别落在n - 1个区间内。

觉得可以用贪心做,开始想了下因为区间有两个端点,而且位置任意,有点不好处理。后来就想先以一个端点排序,以另一个端点作为贪心准则。首先对于所有的区间,我们按右端点递增排序。左端点不予考虑。并将所有的数(即桥长)递增排序。然后依次遍历每个区间,然后从剩下的数中找最小的可以满足这个区间的数去满足这个区间,如果找不到则直接输出No。下面我们证明这个思路的正确性。用数学归纳法即可证明。

对于第一个区间[L1,R1],若有某两个数都能满足这个区间,设较小的数为min,较大的数为max,如果我们用max去满足这个区间的话:

1、若最后的解中min没有被用来满足任何区间,那么我们将max换为min,不影响结果,因此我们可以使用min去满足这个区间。

2、若最后的解中min满足了某个其他的区间 [L2,R2],则 [L2,R2] 必定排序在 [L1,R1] 的后面(因为 [L1,R1] 是第一个区间),故有R2 ≥ R1,L2 ≤ min ≤ R2。因为min也同时满足 [L1,R1],所以必有L2 ≤ R1。由max在 [L1,R1] 区间可知max ≤ R1。故有L2 ≤ min ≤ max ≤ R1 ≤ R2,即L2 ≤ max ≤ R2,也就是max同时也满足 [L2,R2] 区间。因此这个两个数分别同时满足这两个区间。我们将它们互换,并不影响结果,同样可以使得min去满足
[L1,R1]这个区间。

假如我们按上述方法满足了前k个区间。那么对于第k + 1个区间[L1,R1],若还是有两个数(这两个数暂时均未被用来满足任何区间)能满足此区间,仍设较小的数为min,较大的数为max,如果我们用max去满足这个区间的话:

1、若最后的解中min没有被用来满足任何区间,那么我们将max换为min,不影响结果,因此我们可以使用min去满足这个区间。

2、若最后的解中min满足了某个其他的区间 [L2,R2],若 [L2,R2] 排序在 [L1,R1] 之前,那么我们会在先前选择满足 [L2,R2] 这个区间的数时,就将这个数用来满足 [L2,R2] 区间了,于是在选择满足当前区间 [L1,R1] 的数时,min已经被满足于先前的区间(即 [L2,R2])。矛盾。因此 [L2,R2] 必定排序在 [L1,R1] 的后面。这样的话,按照刚才的分析,仍可以用min去满足 [L1,R1]这个区间。

故这样的贪心准则是可行的。对于每个区间要从剩下的数中找最小的满足区间的数可以二分,但是二分之后要删去这个数(因为后面不再用到)所以这里用mult_set实现。

/*----------------------

虽然是第一次打div1。。。。。

然而并不想打div1。。。。。

但是rating涨上去了又不得不打div1。。。。。

然而打了又不得不掉rating下次继续打div2。。。。。

好纠结啊。。。。。

以后只要再被逼无奈打div1。。。。。

我一定像这次一样坐等掉rating然后去打div2。。。。。

I LOVE AC

AC_FirstLucker

----------------------*/

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#include <set>
using namespace std;

struct Bridge //桥
{
    int id;
    long long lenth;
};

struct Range //区间
{
    int id;
    long long l;
    long long r;
};

const int MAX = 200005;

int n, m;
Range range[MAX];
Bridge temp[MAX]; //先用数组排序后再插入到集合中
multiset <Bridge> bridge;

bool operator < (Range r1, Range r2)
{
    return r1.r < r2.r;
}

bool operator < (Bridge b1, Bridge b2)
{
    return b1.lenth < b2.lenth;
}

void input()
{
    long long x, y, tx, ty;
    scanf("%I64d%I64d", &tx, &ty);
    for(int i = 0; i < n - 1; i++)
    {
        scanf("%I64d%I64d", &x, &y);
        range[i].id = i;
        range[i].l = x - ty;
        range[i].r = y - tx;
        tx = x;
        ty = y;
    }
    for(int i = 0; i < m; i++)
    {
        scanf("%I64d", &temp[i].lenth);
        temp[i].id = i;
    }
}

void solve()
{
    int ans[MAX]; //记录答案
    sort(range, range + n - 1);
    sort(temp, temp + m);
    bridge.clear();
    for(int i = 0; i < m; i++)
        bridge.insert(temp[i]);
    for(int i = 0; i < n - 1; i++)
    {
        Bridge value;
        value.lenth = range[i].l;
        set <Bridge>::iterator it = bridge.lower_bound(value);
        if((*it).lenth < range[i].l || (*it).lenth > range[i].r) //找不到任何可以满足当前区间的桥
        {
            printf("No\n");
            return;
        }
        ans[range[i].id] = (*it).id; //用找到的桥满足这个区间
        bridge.erase(it); //删除当前找到的桥
    }
    printf("Yes\n");
    for(int i = 0; i < n - 1; i++)
    {
        if(i > 0)
            printf(" ");
        printf("%d", ans[i] + 1);
    }
    printf("\n");
}

int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
    {
        input();
        solve();
    }
    return 0;
}





版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-09 08:04:36

Codeforces 555B - Case of Fugitive 搭桥的相关文章

codeforces 555B Case of Fugitive

题目连接: http://codeforces.com/problemset/problem/555/B 题目大意: 有n个岛屿(岛屿在一列上,可以看做是线性的,用来描述岛屿位置的是起点与终点),m个桥,给出每个岛屿的位置和桥的长度,问是否可以把n个岛屿连起来? 解题思路: 排序+贪心,对于n个岛屿,相邻的两个之间起点和端点可以转化为n-1个连接桥的长度区间,把区间升序排列. 对于m个桥升序排列,对于每一个桥枚举每个可以合法覆盖的区间,选取最优的,选取的时候满足L<bridge_length<

codeforces 555b//Case of Fugitive// Codeforces Round #310(Div. 1)

题意:有n-1个缝隙,在上面搭桥,每个缝隙有个ll,rr值,ll<=长度<=rr的才能搭上去.求一种搭桥组合. 经典问题,应列入acm必背300题中.属于那种不可能自己想得出来的题.将二元组[ll,rr]排序(ll相同时再rr),长度x排序(升序).一个全局优先队列pq(rr小的顶部).for循环,对每个x,将ll比它小的放入优先队列pq,如果pq仍为空,说明这块桥用不上,不为空,看top的rr是否大于x,如果大于,这块桥就能用上,并且给当前的top一定是可行的. 乱码: #pragma co

Codeforces 556D - Case of Fugitive

556D - Case of Fugitive 思路:将桥长度放进二叉搜索树中(multiset),相邻两岛距离按上限排序,然后二分查找桥长度匹配并删除. 代码: #include<bits/stdc++.h> using namespace std; #define ll long long const int N=2e5+5; struct node { ll x; ll y; int id; bool operator <(const node &a)const { ret

CodeForces - 556D Case of Fugitive (贪心+排序)

Andrewid the Android is a galaxy-famous detective. He is now chasing a criminal hiding on the planet Oxa-5, the planet almost fully covered with water. The only dry land there is an archipelago of n narrow islands located in a row. For more comfort l

Round 310(Div.1) B. Case of Fugitive

Round 310(Div.1) B. Case of Fugitive Andrewid the Android is a galaxy-famous detective. He is now chasing a criminal hiding on the planet Oxa-5, the planet almost fully covered with water. The only dry land there is an archipelago of n narrow islands

codeforces 556 D Case of Fugitive

这个题很显然,可以转换成这个问题: 有n-1个区间,m个数, 每个数最多只能用一次,第i个数只要能被第j个区间包含,那么这个数就可以放入这个区间内. 求出,当所有区间里都恰有一个数时的情况. 我们把所有区间按照下限升序排序,所有数升序排序之后分治即可. 分治过程,维护一个元素为区间的小堆,堆顶是上限最小的区间. 考虑第i个数,把所有能够包含它的区间都丢到堆中,然后从堆中丢一个区间出来,若这个区间可以包含这个数,那么记录下来,否则无解,结束程序. 为什么此时无解呢?因为很显然后面的数都不小于这个数

CodeForces - 556C Case of Matryoshkas

Andrewid the Android is a galaxy-famous detective. He is now investigating the case of vandalism at the exhibition of contemporary art. The main exhibit is a construction of n matryoshka dolls that can be nested one into another. The matryoshka dolls

codeforces 556B. Case of Fake Numbers 解题报告

题目链接:http://codeforces.com/problemset/problem/556/B 题目意思:给出 n 个齿轮,每个齿轮有 n 个 teeth,逆时针排列,编号为0 ~ n-1.每按一次 button,每个齿轮都会有且仅有一个活动的tooth,对于偶数编号的齿轮,它下一个活动tooth是紧挨着当前tooth的逆时针方向的那个:而奇数编号的齿轮,下一个活动tooth是顺时针的那个.给出每个齿轮的活动tooth,问通过按下有限次的button,问能不能得到一个0,1,...,n-

[CF310]D. Case of Fugitive

题意: 给出n个线段,在n个线段之间搭桥,给出m个桥的长度,假如满足条件 To reach the goal, Andrewid needs to place a bridge between each pair of adjacent islands. A bridge of length a can be placed between the i-th and the (i?+?1)-th islads, if there are such coordinates of x and y, t