hdu6003 Problem Buyer 贪心 给定n个区间,以及m个数,求从n个区间中任意选k个区间,满足m个数都能在k个区间中找到一个包含它的区间,如果一个区间包含了x,那么 该区间不能再去包含另一个数,即k>=m。求最小的k。如果不存在这样的k,输出“IMPOSSIBLE!”。
/** 题目:hdu6003 Problem Buyer 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6003 题意:给定n个区间,以及m个数,求从n个区间中任意选k个区间,满足m个数都能在k个区间中找到一个包含它的区间,如果一个区间包含了x,那么 该区间不能再去包含另一个数,即k>=m。求最小的k。如果不存在这样的k,输出“IMPOSSIBLE!”。 思路:贪心; 对n个区间,先左端点进行由小到大排序,然后右端点由大到小。对m个数由小到大排序。 对m个数进行枚举,设枚举数x,从排好序的区间左边开始找包含x的区间,放入优先队列q,那么队列里的都是包含x的区间,其他不包含它。 那么如果要满足题目要求,k>=n-q.size()+1;注意n-q.size()+1这个值不一定是该条件下m个数都能找到匹配区间的值,而是最少值。 因为剩下的n-q.size()不一定可以匹配所有的m-1个区间。可能有些数要匹配它的区间在q里面。不过没关系,只要这样进行下去,总会 找到一个最优值,详细证明, 大致说一下: 假设剩下的n-q.size()可以覆盖所有的m-1数,那么n-q.size()+1就是当前答案。 假设剩下的n-q.size()不可以覆盖所有的m-1数: 分两种情况。 1,剩下的某个数存在永远无法包含它的区间,那么可以解决,具体看代码,当为-1的时候,表示该数永远包含不到。 2,假设x个数在剩下的n-q.size()个区间无法包含,那么该x个数可以包含他们的区间在q里面。如果x+1>q.size(),那么-1,可以解决。 如果x+1<=q.size()。那么当前的n-q.size()+1不是当前答案,而是可能的至少值。随着向右进行(看代码),q.size()不断变化,总会存在一个最优的情况 使得q里面的区间只包含m正在枚举的这个数。 。具体看代码实现。 */ #include<iostream> #include<cstdio> #include<algorithm> #include<map> #include<vector> #include<queue> #include<cstring> using namespace std; typedef pair<int,int> P; typedef long long LL; const int N = 1e5+100; const int INF = 0x3f3f3f3f; struct node { int l, r; bool operator < (const node&k)const{ if(l==k.l) return r>k.r; return l<k.l; } }t[N]; int c[N]; int main() { int T, n, m; int cas = 1; cin>>T; while(T--) { scanf("%d%d",&n,&m); for(int i = 0; i < n; i++){ scanf("%d%d",&t[i].l,&t[i].r); } for(int i = 0; i < m; i++) scanf("%d",&c[i]); sort(t,t+n); sort(c,c+m); priority_queue<int, vector<int>, greater<int> > q; int pos = 0; int ans = 0; for(int i = 0; i < m; i++){ while(pos<n&&t[pos].l<=c[i]){ if(t[pos].r>=c[i]) q.push(t[pos].r); pos++; } while(!q.empty()&&q.top()<c[i]) q.pop(); if(q.empty()){ ans = -1; break; } ans = max(ans,n-(int)q.size()+1); q.pop(); } if(ans==-1) printf("Case #%d: IMPOSSIBLE!\n",cas++); else printf("Case #%d: %d\n",cas++,ans); } return 0; }
posted on 2017-07-27 10:51 hnust_accqx 阅读(1289) 评论(0) 编辑 收藏 举报