• 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;
    }
    

      

  • 相关阅读:
    hadoop学习笔记(十):MapReduce工作原理(重点)
    hadoop学习笔记(九):MapReduce程序的编写
    hadoop学习笔记(八):MapReduce
    hadoop学习笔记(七):Java HDFS API
    hadoop学习笔记(六):HDFS文件的读写流程
    hadoop学习笔记(五):HDFS Shell命令
    hadoop学习笔记(四):HDFS
    hadoop学习笔记(三):hadoop文件结构
    立即执行函数
    let命令
  • 原文地址:https://www.cnblogs.com/ljh2000-jump/p/6258705.html
Copyright © 2020-2023  润新知