给你n个岛屿的左右端点(l.r)(此题岛屿不是点,是一个区间)
给你m个桥
题目要求桥大于等于两个岛屿之间的 min距离,且小于等于其max距离,min=bridge(i+1).L-bridge(i).r。 max=bridge(i+1).r-bridge(i).l;
思路:
先对桥排序
再对岛屿排序,应该先对max距离从小到大排序,max相同则对min从小到大排序
关键就是 要 选桥的时候,优先考虑 max值最小的岛屿, 对于他们来说,选择一条 最接近min值的桥一定是最优的
对于当前这个max最小的岛屿,用他的min在 桥里面二分找到第一个恰好大于等于min的len,
如果len>max|| 找不到满足条件的桥len,那么此两岛屿肯定无解(因为之后的桥的len肯定大于当前的len,也就是不可能出现len<=max)
如果len<=max,那么必为最优解,因为不可能出现 此后的岛屿对只能选当前的桥才合法(比较难证明...233)
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define inf 1223372036854775807
struct node
{
__int64 l,r;
};
node tm[200005];
struct DISTANCE
{
__int64 mi,mx;
__int64 num;
__int64 bb;
};
__int64 cmp(DISTANCE a,DISTANCE b)
{
if (a.mx!=b.mx)
return a.mx<b.mx;
else
return a.mi<b.mi;
}
__int64 final_cmp(DISTANCE a,DISTANCE b)
{
return a.num<b.num;
}
struct BRI
{
__int64 len,num;
bool operator<( const BRI& b) const
{
if (len!=b.len)
return len<b.len;
else
return num<b.num;
}
bool operator==( const BRI& b) const
{
return len==b.len&&num==b.num;
}
};
DISTANCE dis[200005];
set <BRI> bri;
set <BRI> ::iterator it;
int main()
{
__int64 n,m;
__int64 i,j;
scanf("%I64d%I64d",&n,&m);
for (i=1;i<=n;i++)
{
scanf("%I64d%I64d",&tm[i].l,&tm[i].r);
}
for (i=1;i<=n-1;i++)///dis[i]---i??i+1????????????Χ
{
dis[i].mi=tm[i+1].l-tm[i].r;
dis[i].mx=tm[i+1].r-tm[i].l;
dis[i].num=i;
}
sort(dis+1,dis+1+n-1,cmp);
__int64 tt;
for (i=1;i<=m;i++)
{
scanf("%I64d",&tt);
BRI tp;
tp.len=tt;
tp.num=i;
bri.insert(tp);
}
for (i=1;i<=n-1;i++)
{
BRI tp;
tp.len=dis[i].mi;
tp.num=0;
it= bri.lower_bound(tp);
if ((*it).len >dis[i].mx||it==bri.end())
break;
else
{
dis[i].bb=it->num;
BRI del;
del.len=it->len;
del.num=it->num;
bri.erase(del);
}
}
if (i==n)
{
printf("Yes\n");
sort(dis+1,dis+n,final_cmp);
for (i=1;i<=n-1;i++)
{
if (i!=1) printf(" ");
printf("%I64d",dis[i].bb);
}
printf("\n");
}
else
{
printf("No\n");
}
return 0;
}