Codeforces Round #390 (Div. 2) D. Fedor and coupons(区间最大交集+优先队列)
2017-06-26 14:34
387 查看
http://codeforces.com/contest/754/problem/D
题意:
给定几组区间,找k组区间,使得它们的公共交集最大。
思路:
在k组区间中,它们的公共交集=k组区间中右端点最小值-k组区间中左端点最大值。如果我们要区间大,那我们应该尽量让左端点小,右端点大。
先对区间按照左端点排序,然后用优先队列处理。
将区间按照左端点从小到大的顺序一一进队列,只需要进右端点即可,如果此时队列内已有k个数,则队首就是这k组区间的最小右端点,而因为左端点是从小到大的顺序进队列的,所以这k组区间中左端点最大的就是当前进队列的区间,这样一来就可以算出在这种情况下的区间交集。如果此时队列内已有k+1个数,那么就弹出队首元素,因为此时弹出的区间右端点是最小的,而我们想要是的尽量大的右端点。
题意:
给定几组区间,找k组区间,使得它们的公共交集最大。
思路:
在k组区间中,它们的公共交集=k组区间中右端点最小值-k组区间中左端点最大值。如果我们要区间大,那我们应该尽量让左端点小,右端点大。
先对区间按照左端点排序,然后用优先队列处理。
将区间按照左端点从小到大的顺序一一进队列,只需要进右端点即可,如果此时队列内已有k个数,则队首就是这k组区间的最小右端点,而因为左端点是从小到大的顺序进队列的,所以这k组区间中左端点最大的就是当前进队列的区间,这样一来就可以算出在这种情况下的区间交集。如果此时队列内已有k+1个数,那么就弹出队首元素,因为此时弹出的区间右端点是最小的,而我们想要是的尽量大的右端点。
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<sstream> #include<vector> #include<stack> #include<queue> #include<cmath> #include<map> #include<set> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int INF = 0x3f3f3f3f; const int maxn=3*1e5+5; int n, k; struct node { int l, r; int id; bool operator < (const node& rhs) const { return l<rhs.l || (l==rhs.l && r<rhs.r); } }p[maxn]; struct cmp { bool operator() (const int a, const int b) const { return a > b; } }; int main() { // freopen("in.txt","r",stdin); while(~scanf("%d%d",&n, &k)) { for(int i=1; i<=n; i++) { scanf("%d%d",&p[i].l, &p[i].r); p[i].id = i; } sort(p+1,p+n+1); priority_queue<int, vector<int>, cmp > Q; int ans=0, left, right; for(int i=1;i<=n;i++) { Q.push(p[i].r); if(Q.size()>k) Q.pop(); if(Q.size()==k) { int tmp=Q.top()-p[i].l+1; if(tmp>ans) { ans=tmp; left=p[i].l; right=Q.top(); } } } if(ans<=0) { puts("0"); for(int i=1;i<=k;i++) { printf("%d%c",i,i==k?'\n':' '); } } else { printf("%d\n",ans); for(int i=1;i<=n;i++) { if(p[i].l<=left && p[i].r>=right) { printf("%d",p[i].id); k--; if(k) printf(" "); else {printf("\n");break;} } } } } return 0; }
相关文章推荐
- Codeforces Round #390 (Div. 2)DFedor and coupons (排序+优先队列)
- Codeforces Round #390 (Div. 2)D Fedor and coupons
- Codeforces Round #390 (Div. 2) D. Fedor and coupons
- Codeforces Round #329 (Div. 2) B. Anton and Lines ([好题] 计算直线在区间是否有交点)
- codeforces D. Fedor and coupons 贪心+优先队列
- Educational Codeforces Round 37 (Rated for Div. 2) F. SUM and REPLACE(线段树,区间更新)
- 【Codeforces Round 331 (Div 2)C】【脑洞 SET贪心写法】Wilbur and Points 锯齿图形差值编号,右上角的最大
- 【Codeforces Round 370 (Div 2) E】【线段树 等比数列 区间合并】Memory and Casinos 赌场区间[l,r] l进r先出的概率
- 【Codeforces Round 169 (Div 2) D】【简单数位贪心】Little Girl and Maximum XOR 区间选两数使得异或值尽可能大
- 【Codeforces Round 365 (Div 2)D】【离线询问 树状数组 前驱思想】Mishka and Interesting sum 区间内出现次数偶数的数的异或和
- 【Codeforces Round 263 (Div 2)C】【贪心 哈弗曼思维】Appleman and Toastman 每个非1size子树延展为2子树的最大权
- Codeforces Round #186 (Div. 2) D. Ilya and Roads(区间类动态规划)
- Codeforces Round #390 (Div. 2)-B Ilya and tic-tac-toe game(模拟)
- 【Codeforces Round 169 (Div 2) E】【数据结构区间维护】Little Girl and Problem on Trees 大菊花树的距离性修改查询
- 【Codeforces Round 331 (Div 2)D】【DP 记忆化搜索 期望DP区间性质 好题】Wilbur and Trees 砍树随机从右从左概率左倒右倒的期望底面覆盖长度
- Codeforces Round #390 (Div. 2) C. Vladik and chat (DP/记忆化搜索)
- Codeforces Round #267 (Div. 2) B. Fedor and New Game
- Codeforces Round #390(Div. 2)B. Ilya and tic-tac-toe game【模拟】
- Codeforces Round #195 (Div. 2) D题Vasily the Bear and Beautiful Strings
- Codeforces Round #199 (Div. 2) A. Xenia and Divisors