给你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; }