R310 DIV2 D. Case of Fugitive
飞机票:http://codeforces.com/contest/556/problem/D
题意:给你n个区间li,ri,且ri<li+1,(1<=i<n),li<=ri,然后给你m座桥,每个有个长度ai,然后要求把桥搭在区间上,且满足桥的长度
大于等于li+1-ri,且小于等于ri+1-li,求能否用桥把所有的相邻区间连接起来,并且输出每个相邻区间对应的桥下标。
分析:起先一看以为是二分图,但是看边太多直接放弃。这里我们 可以知道一个东西。就是相邻区间需要的桥的最大值和最小值,假设两个相邻区间li,ri li+1,ri+1,我们定义他们的坐标为i,则可知需要的最小长度为li+1-ri,最大长度为ri+1-li,假设为最小为le最大为ri,接着我们再把m条桥排序,从小到大。接着运用贪心看看怎么贪?假设当前要判断桥i属于哪个区间le ri,我们必须把所有可以用桥i的区间找出来,然后找右端点最小的,为什么?因为大伙都可以用它,当然我们要使用剩余使用量最小的来接受它,不然给别人,它都亏。搞到这里就知道怎么贪了吧。就是把le ri按左区间排序,如果一样不用管。然后来个优先队列,假如当前的le<=桥i的长度,就把它加到优先队列,为什么??因为我们不知道它满不满足,但是只要它的右端点最小,然后比桥i的长度还短,那么直接就No了,因为别人都比它好。优先队列干嘛用的?就是取右端点最小的,因为我们前面判断过的比较小的le可能要在这个时候用到。总体复杂的就是O(n*logn)了。然后啪啪啪就可以AC了
/* Author:Chieh Because Of Coding */ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <map> #include <stack> #include <vector> #include <queue> #define LL long long #define INF 1e9 #define EPS 1e-9 using namespace std; const int maxn=2*123456; LL l[maxn],r[maxn]; struct he { int id; LL l,r; bool operator<(const he& a)const { return r>a.r; } } Sky[maxn]; LL ai[maxn]; struct he1 { LL val; int id; } Sky1[maxn]; int can[maxn]; int n,m; bool cmp(he1 a,he1 b) { return a.val<b.val; } void init() { for(int i=1; i<=n; i++) { scanf("%I64d%I64d",&l[i],&r[i]); } for(int i=1; i<=m; i++) { scanf("%I64d",&Sky1[i].val); Sky1[i].id=i; } sort(Sky1+1,Sky1+1+m,cmp); } bool cmp2(he a,he b) { if(a.l!=b.l)return a.l<b.l; return a.r<b.r; } priority_queue<he> pq; void play() { int st=0; for(int i=2; i<=n; i++) { LL a1=l[i]-r[i-1]; LL a2=r[i]-l[i-1]; st++; Sky[st].l=a1; Sky[st].r=a2; Sky[st].id=st; } sort(Sky+1,Sky+1+st,cmp2); while(!pq.empty())pq.pop(); int now=1; for(int i=1; i<=m; i++) { int id=Sky1[i].id; LL val=Sky1[i].val; while(now<=st) { if(Sky[now].l<=val) { pq.push(Sky[now]); now++; } else { break; } } if(pq.empty())continue; he aa=pq.top(); pq.pop(); if(aa.r<Sky1[i].val) { printf("No\n"); return; } int idx=aa.id; can[idx]=id; } if(!pq.empty()||now!=st+1) { printf("No\n"); return ; } printf("Yes\n"); for(int i=1; i<=st; i++) { printf("%d ",can[i]); } printf("\n"); } int main() { while(scanf("%d%d",&n,&m)!=EOF) { init(); play(); } // cout << "Hello world!" << endl; return 0; }