大意:有若干岛屿分布在坐标轴上,每个岛屿给出左右边界,桥两端必须架在岛上,现在求一个方案在这些岛屿上架桥。
思路:比赛的时候abc做得好慢。。。看d的时候一下就发现是做过的题,然而没时间写(事实证明我写了1个多小时。。),对于每一个岛屿间隙,都有一个桥的可行长度范围,记为,i,r,则把桥的长度升序排列,间隙按l升序排列,然后对于每一座桥,把这座桥可以搭建的间隙全部入队,优先队列的堆顶取出的元素是r最小的元素,如果堆顶元素的r<现在的桥的长度,那么无解,否则一直继续下去,最后判断用掉的桥有多少即可。。。。这题的输出也很蛋疼,间隙和桥都要输出原来的编号。。。搞得好麻烦。。。
#include<bits/stdc++.h> #define pb push_back using namespace std; typedef long long ll; struct STR{ ll f,s; ll o; bool operator < (const STR &C)const{ return s>C.s; } }; bool cmp1(STR a,STR b){ if(a.f!=b.f) return a.f<b.f; else return a.s<b.s; } const int maxv=2e5+40; STR read[maxv]; struct BRI{ ll l,o; }; bool cmp2(BRI a,BRI b){ return a.l<b.l; } class cmp3{ public: bool operator() (BRI a,BRI b){ return a.l<b.l; } }; BRI bridge[maxv]; priority_queue<STR> Q; int n,m; struct ANS{ ll b,o; }; bool cmp4(ANS a,ANS b){ return a.o<b.o; } vector<ANS> ans; int main(){ ////freopen("/home/files/CppFiles/in","r",stdin); cin>>n>>m; for(int i=0;i<n;i++){ cin>>read[i].f>>read[i].s; } for(int i=0;i<m;i++){ cin>>bridge[i].l; bridge[i].o=i+1; } sort(bridge,bridge+m,cmp2); sort(read,read+n,cmp1); for(int i=0;i<n-1;i++){ ll tf=read[i+1].f-read[i].s; ll ts=read[i+1].s-read[i].f; read[i].f=tf;read[i].s=ts; read[i].o=i; }; n--; sort(read,read+n,cmp1); int h=0; int added=0; for(int i=0;i<m;i++){ while(h<n&&bridge[i].l>=read[h].f){ Q.push(read[h]); h++; } if(Q.empty()){ continue; }else{ if(Q.top().s<bridge[i].l){ cout<<"No"<<endl; return 0; }else if(Q.top().f<=bridge[i].l){ ans.pb((ANS){bridge[i].o,Q.top().o}); Q.pop(); added++; } } } if(added<n){ cout<<"No"<<endl; return 0; } cout<<"Yes"<<endl; sort(ans.begin(),ans.end(),cmp4); for(int i=0;i<ans.size();i++) cout<<ans[i].b<<" "; return 0; }