codeforces #310 B B. Case of Fugitive(贪心)

题目链接:

点击打开链接

题目大意:

给出一些桥,给出一些不重叠的区间,在区间之间架桥,给出方案

题目分析

首先我们先把区间转换为区间的缝隙,和两个区间加缝隙的总长,架的每一座桥要满足大于缝隙但小于总长,所以说对于最小的桥,要选择的是它可选范围内缝隙最小的一个区间,因为后面的桥均大于它,所以说不用担心后面的桥的缝隙太大导致后面的桥不可选,但很可能因为总长台小导致后面的桥不能选这一区间,所以说要按前面所说的方法选,那么我们先将桥排序,然后对区间处理后的缝隙和总长记录下的结构体按照缝隙排序,当出现桥符合当前要求时,将当前区间放入优先队列(如上述按照总长小的优先级大),因为是按缝隙排的序,所以当前如果缝隙如果在当前情况下符合要求,那么之后一定符合,而总长在之后可能因为过短被舍去,而当前不符合条件的总长在之后也一定不会编程符合要求的总长,那么这样的话,我们就可以O(n)的解决这个问题了,前面排序是nlogn

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#define MAX 200007

using namespace std;

typedef long long LL;

int n,m;
LL l[MAX],r[MAX];
int ans[MAX];

struct Seg
{
    LL l,r;
    int id;
    bool operator < ( const Seg & a ) const 
    {
        return r > a.r;
    }
}a[MAX],b[MAX];

bool cmp ( Seg a , Seg b )
{
    return a.l < b.l;
}

struct Node
{
    LL v;
    int id;
    bool operator < ( const Node& a ) const
    {
        if ( v == a.v ) return id < a.id;
        return v < a.v;
    }
}p[MAX];

int main ( )
{
    while ( ~scanf ( "%d%d" , &n , &m ) )
    {
        for ( int i = 0 ; i < n ; i++ )
            scanf ( "%I64d%I64d" , &b[i].l , &b[i].r );
        for ( int i = 0 ; i < n-1 ; i++ )
        {
            a[i].l = b[i+1].l - b[i].r;
            a[i].r = b[i+1].r - b[i].l;
            a[i].id = i;
        }
        for ( int i = 0 ; i < m ; i++ )
        {
            scanf ( "%I64d" , &p[i].v );
            p[i].id = i+1;
        }
        sort ( a , a+n-1 , cmp );
        sort ( p , p+m );
        priority_queue<Seg> q;
        int j = 0;
        int num = 0;
        for ( int i = 0 ; i < m ; i++ )
        {
            //cout << "OKAY! " << endl;
            while ( !q.empty() && (q.top().r < p[i].v ) )
                q.pop();
            while ( j < n-1 && a[j].r >= p[i].v && a[j].l <= p[i].v )
            {
                q.push ( a[j] );
                j++;
            }
            //cout << "YES " << endl;
            if ( q.empty() ) continue;
            Seg temp = q.top();
            q.pop();
            ans[temp.id] = p[i].id; 
            //cout << "YES" <<temp.l << " " << temp.r << endl;
            num++;
        } 
        //cout << "YES : " << num << endl;
        if ( num == n-1 )
        {
            puts("Yes");
            for ( int i = 0 ; i < n-1 ; i++ )
                printf ( "%d " , ans[i] );
            puts("");
        }
        else puts("No");
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值