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 21 10040 70120 130125 180

output

311 2 

input

3 21 1215 2025 30

output

01 2 

input

5 21 105 1514 5030 7099 100

output

213 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\n",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;
}

  

时间: 2024-10-29 19:50:46

codeforces754D Fedor and coupons的相关文章

Codeforces-754D Fedor and coupons

传送门 给你n(<=3e5)个区间,让你从中选出k(<=n)个,使这些区间的交集长度最大.区间范围[-1e9, 1e9] 要求输出区间长度和选取的区间编号 典型的优先队列问题.先把区间按左值从小到大排序,这样做保证了后面取出来的区间的左值大于先前所有的,然后我门就只需要比较右值了.注意到最终答案的区间是由k个区间交,所以我们要维护k个区间的信息.每次由这k个右值里的最小值来减去k个左值里的最大值再加一去更新答案.由于最后取出的区间的左值最大(排序过),所以我们维护k个右值即可.选取优先队列维护

CodeForces 754D Fedor and coupons ——(k段线段最大交集)

还记得lyf说过k=2的方法,但是推广到k是其他的话有点麻烦.现在这里采取另外一种方法. 先将所有线段按照L进行排序,然后优先队列保存R的值,然后每次用最小的R值,和当前的L来维护答案即可.同时,如果Q的size()比k大,那么就弹出最小的R. 具体见代码: 1 #include <stdio.h> 2 #include <algorithm> 3 #include <string.h> 4 #include <set> 5 #include <vec

cf754 754D - Fedor and coupons

2个多小时,弱智了..(连A都做不对,就不要做D了(迷)) 1 #include<bits/stdc++.h> 2 #define lowbit(x) x&(-x) 3 #define LL long long 4 #define N 100005 5 #define M 1000005 6 #define mod 2147483648LL 7 #define inf 0x7ffffffff 8 using namespace std; 9 inline int ra() 10 { 1

CodeForces 754D Fedor and coupons (优先队列)

题意:给定n个优惠券,每张都有一定的优惠区间,然后要选k张,保证k张共同的优惠区间最大. 析:先把所有的优惠券按左端点排序,然后维护一个容量为k的优先队列,每次更新优先队列中的最小值,和当前的右端点, 之间的距离.优先队列只要存储右端点就好. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <

Codeforces Round #390 (Div. 2) 解题报告

时隔一个月重返coding…… 期末复习了一个月也不亏 倒是都过了…… 就是计组61有点亏 复变68也太低了 其他都还好…… 假期做的第一场cf 三道题 还可以…… 最后room第三 standing383简直人生巅峰…… 看楼上楼下都是两道题的 如果A题不错那么多估计能进前300了吧…… 这场倒是把之前两场的分加回来了 开头不错 这个假期争取紫名~ A.Lesha and array splitting 把给定的数组分割成几个区间 要求各个区间和不能为0 一开始没注意到分割之后的区间重新合成之

Codeforces Round #390 (Div. 2)

22:35-0:35  1.6.2017 A.Lesha and array splitting 题意:自己看 题解: 构造什么的最弱了 想了想,貌似除了0每个数单独一组就可以,只要有一个非0数则一定可以有解 0的话不停往前找到第一个非0然后合为一组 第一个数是0怎么办?先让第一个数往后找一个非0呗 比赛的时候智商骤减,写的代码好难看还写了好长时间,并且还WA一次...应该可以很简洁的吧 #include<iostream> #include<cstdio> #include<

hackerrank Alex对战Fedor

任意门 为了在漫长得飞行旅途中娱乐,Alex和Fedor发明了如下的一个简单的双人游戏.游戏是: 首先, Alex画一个有权无向图.该图中可能有多重边(多重边的权值可能相同或者不同). 然后,Fedor选取该图的一个生成树.如果该树是这个图的最小生成树,则Fedor获胜.否则,Alex获胜. 如果两棵树分别包含的边标号形成的两个集合不相同,我们认为这两棵树不同.两个集合A和B,如果至少存在一个元素在A中但不在B中,或者反之,至少存在一个元素在B中但不在A中,则我们认为这两个集合不同. 我们还要指

Codeforces 467D Fedor and Essay(bfs)

题目链接:Codeforces 467D Fedor and Essay 题目大意:给定一个含n个单词的文本,然后给定m种变换,要求变换后r的个数尽量少,长度尽量短,不区分大小写. 解题思路:bfs,将每个单词处理成长度以及r的个数,然后从最优的开始更新即可,类似dp. #include <cstdio> #include <cstring> #include <map> #include <string> #include <vector> #

UVA - 10288 Coupons (概率+递推)

Description Problem F Coupons Input: standard input Output: standard output Time Limit: 2 seconds Memory Limit: 32 MB Coupons in cereal boxes are numbered 1 to n, and a set of one of each is required for a prize (a cereal box, of course). With one co