题目链接:
题目大意:
给出一些桥,给出一些不重叠的区间,在区间之间架桥,给出方案
题目分析
首先我们先把区间转换为区间的缝隙,和两个区间加缝隙的总长,架的每一座桥要满足大于缝隙但小于总长,所以说对于最小的桥,要选择的是它可选范围内缝隙最小的一个区间,因为后面的桥均大于它,所以说不用担心后面的桥的缝隙太大导致后面的桥不可选,但很可能因为总长台小导致后面的桥不能选这一区间,所以说要按前面所说的方法选,那么我们先将桥排序,然后对区间处理后的缝隙和总长记录下的结构体按照缝隙排序,当出现桥符合当前要求时,将当前区间放入优先队列(如上述按照总长小的优先级大),因为是按缝隙排的序,所以当前如果缝隙如果在当前情况下符合要求,那么之后一定符合,而总长在之后可能因为过短被舍去,而当前不符合条件的总长在之后也一定不会编程符合要求的总长,那么这样的话,我们就可以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");
}
}