【codeforces 754D】Fedor and coupons

time limit per test4 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
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 n discount 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 k coupons 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.

【题目链接】:http://codeforces.com/contest/754/problem/D

【题解】

题意:
给你N个区间,让你从中选出K个区间,要求这K个区间的并集的大小最大;
做法:
将所有的区间的左端点升序排;
然后从左到右依次处理区间;
在处理区间的过程中,维护大小为K-1的区间的右端点的一个优先队列;(队首最小,递增)
每处理到一个区间i;
如果队列的大小为K-1则更新答案ans
ans = max(ans,min(a[i].r-a[i].l+1,que.top()-a[i].l+1));
然后把a[i].r加入队列,如果队列大小大于k-1,则pop()->去掉最小的那个元素;
因为我们每次都去掉最小的右端点;
则我们在处理第i个区间的时候,肯定是尽可能的增加这个a[i].l的“价值”;
尽量用一个更大的r和它配对;
这样贪心地想一下
每次枚举的区间当然就是最大的符合要求的区间了;
因为我们枚举了每一个区间的左端点,作为最后的答案区间的左端点;
因此算法是正确的;
又根据这个题目的对称性(那个区间肯定是被k-1个左端点,k-1个右端点包围的);
所以如果从右往左,也只能得到相同的答案,因此没必要再按右端点升序排再从
右到左处理;
最后O(N)
找一下区间范围在答案区间内的K个区间就好(任意都可以,只要包括);

【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define rei(x) scanf("%d",&x)
#define rel(x) scanf("%I64d",&x)

typedef pair<int,int> pii;
typedef pair<LL,LL> pll;

//const int MAXN = x;
const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);

int n,k;
vector <pair<pii,int> > v;
priority_queue <int,vector <int>,greater<int> > que;

int main()
{
    //freopen("F:\rush.txt","r",stdin);
    rei(n);rei(k);
    v.resize(n);
    rep1(i,0,n-1)
        rei(v[i].fi.fi),rei(v[i].fi.se),v[i].se=i+1;
    sort(v.begin(),v.end());
    int ans = 0,L,R;
    rep1(i,0,n-1)
    {
        int len = que.size();
        if (len==k-1)
        {
            int lim = v[i].fi.se-v[i].fi.fi+1;
            if (!que.empty())
                lim = min(lim,que.top()-v[i].fi.fi+1);
            if (lim>ans)
            {
                ans = lim;
                L = v[i].fi.fi;
            }
        }
        que.push(v[i].fi.se);
        len = que.size();
        if (len>k-1)
            que.pop();
    }
    printf("%d
",ans);
    if (ans==0)
        for (int i = 1;i<=k;i++)
            printf("%d ",i);
    for (int i = 0;i<=n-1 && k;i++)
        if (v[i].fi.fi<=L && L+ans-1 <= v[i].fi.se)
        {
            k--;
            printf("%d ",v[i].se);
        }
    return 0;
}
原文地址:https://www.cnblogs.com/AWCXV/p/7626721.html