zoukankan      html  css  js  c++  java
  • codeforces754D Fedor and coupons

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。

    本文作者:ljh2000
    作者博客:http://www.cnblogs.com/ljh2000-jump/
    转载请注明出处,侵权必究,保留最终解释权!

    Description

    All our characters have hobbies. The same is true for Fedor. He enjoys shopping in the neighboring supermarket.

    The goods in the supermarket have unique integer ids. Also, for every integer there is a product with id equal to this integer. Fedor has ndiscount coupons, the i-th of them can be used with products with ids ranging from li to ri, inclusive. Today Fedor wants to take exactly kcoupons with him.

    Fedor wants to choose the k coupons in such a way that the number of such products x that all coupons can be used with this product x is as large as possible (for better understanding, see examples). Fedor wants to save his time as well, so he asks you to choose coupons for him. Help Fedor!

    Input

    The first line contains two integers n and k (1 ≤ k ≤ n ≤ 3·105) — the number of coupons Fedor has, and the number of coupons he wants to choose.

    Each of the next n lines contains two integers li and ri ( - 109 ≤ li ≤ ri ≤ 109) — the description of the i-th coupon. The coupons can be equal.

    Output

    In the first line print single integer — the maximum number of products with which all the chosen coupons can be used. The products with which at least one coupon cannot be used shouldn't be counted.

    In the second line print k distinct integers p1, p2, ..., pk (1 ≤ pi ≤ n) — the ids of the coupons which Fedor should choose.

    If there are multiple answers, print any of them.

    Examples
    input
    4 2
    1 100
    40 70
    120 130
    125 180
    output
    31
    1 2
    input
    3 2
    1 12
    15 20
    25 30
    output
    0
    1 2
    input
    5 2
    1 10
    5 15
    14 50
    30 70
    99 100
    output
    21
    3 4
    Note

    In the first example if we take the first two coupons then all the products with ids in range [40, 70] can be bought with both coupons. There are 31 products in total.

    In the second example, no product can be bought with two coupons, that is why the answer is 0. Fedor can choose any two coupons in this example.

     

    正解:堆+贪心

    解题报告:

      这道题概括出来的模型十分简洁经典:从n条线段中取出恰好k条使得交集长度尽可能长,输出最优值和方案。

      我开始想了很久的单调性,但是并不能实现单调决策,更不能还原历史版本。所以我就想了想,似乎带个log就很可做了?

      考虑先按左端点排序,维护一个右端点坐标的小根堆,那么很容易发现我只需要保证堆的大小始终小于等于k即可。当我每次扫到一个左端点时,将其右端点与堆顶作比较,如果比堆顶小则不作考虑,否则,删除堆顶,把这个新的右端点坐标加入堆中。每次只需用堆顶减去当前处理的线段的左端点来更新答案(当且仅当堆中恰好有k个元素)。输出方案的话,用同样方法再做一次即可。

     

    //It is made by ljh2000
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    #include <ctime>
    #include <vector>
    #include <queue>
    #include <map>
    #include <set>
    #include <string>
    using namespace std;
    typedef long long LL;
    const int MAXN = 300011;
    int n,k,ans,dui[MAXN];
    struct node{int pos,id; inline bool operator < (const node &a)const{ return a.pos<pos; } }tmp;
    priority_queue<node>Q;
    struct seq{int l,r,id;}a[MAXN];
    inline bool cmp(seq q,seq qq){ return q.l<qq.l; }
    inline int getint(){
        int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
        if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
    }
    
    inline void work(){
    	n=getint(); k=getint(); for(int i=1;i<=n;i++) a[i].l=getint(),a[i].r=getint(),a[i].id=i;
    	sort(a+1,a+n+1,cmp); ans=-1;//!!!
    	for(int i=1;i<=n;i++) {
    		if(!Q.empty())tmp=Q.top();		
    		if((int)Q.size()<k) {
    			tmp.pos=a[i].r;
    			tmp.id=i;
    			Q.push(tmp);
    		}
    		else {
    			if(a[i].r>tmp.pos) {
    				Q.pop();			
    				tmp.pos=a[i].r;
    				tmp.id=i;
    				Q.push(tmp);
    			}
    		}
    		if((int)Q.size()>=k) ans=max(Q.top().pos-a[i].l,ans);
    	}
    	printf("%d
    ",ans+1);
    	if(ans==-1) { for(int i=1;i<=k;i++) printf("%d ",i); return ; }
    
    	int lans=ans; ans=-1;
    	while(!Q.empty()) Q.pop();
    	for(int i=1;i<=n;i++) {
    		if(!Q.empty()) tmp=Q.top();		
    		if((int)Q.size()<k) {
    			tmp.pos=a[i].r;
    			tmp.id=a[i].id;//!!!
    			Q.push(tmp);
    		}
    		else {
    			if(a[i].r>tmp.pos) {
    				Q.pop();			
    				tmp.pos=a[i].r;
    				tmp.id=a[i].id;//!!!
    				Q.push(tmp);
    			}
    		}
    		if((int)Q.size()>=k) {
    			ans=max(Q.top().pos-a[i].l,ans);
    			if(ans==lans) {
    				int cnt=0;
    				while(!Q.empty()) {
    					tmp=Q.top();
    					dui[++cnt]=tmp.id;
    					Q.pop();
    				}
    				sort(dui+1,dui+k+1);
    				for(int i=1;i<=k;i++) printf("%d ",dui[i]);
    				return ;
    			}
    		}
    	}
    }
    
    int main()
    {
        work();
        return 0;
    }
    

      

  • 相关阅读:
    【POJ】【2104】区间第K大
    【BZOJ】【2595】【WC2008】游览计划
    【BZOJ】【1036】树的统计
    【BZOJ】【2038】小Z的袜子
    我的博客~
    CSS选择器
    CSS样式表分类
    python奇闻杂技03 三元表达式示例,函数定义示例,七段彩码管绘制示例
    python奇闻杂技02 time模块,文本进度条示例,数字类型操作,字符串操作
    python奇闻杂技01 turtle学习
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6258705.html
Copyright © 2011-2022 走看看