Codeforces Round #390 (Div. 2)

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

题意:给定n个区间,现在让你从这n个区间里面选k个区间,使得这k个区间的交的尽可能的大。

思路:参考HDU 5700区间交。枚举左端点,用multiset维护右端点,因为set自带排序,所以set的第一个元素就是当前最小的右端点,而枚举的i就是当前最大的左端点,然后更新答案。 本题的区间会取值会有负数,所以需要离散化一下。 另外也可以用线段树来实现。

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<stdio.h>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<time.h>
#include<cmath>
using namespace std;
typedef long long int LL;
const int MAXN = 3e5 + 10;
vector<pair<LL,int>>G[MAXN];
pair<LL, LL> p[MAXN];
LL L[MAXN];
int main(){
//#ifdef kirito
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//#endif
//    int start = clock();
    int n,k;
    while (~scanf("%d%d", &n,&k)){
        for (int i = 0; i < MAXN; i++){
            G[i].clear();
        }
        for (int i = 0; i < n; i++){
            scanf("%I64d%I64d", &p[i].first, &p[i].second);
            L[i] = p[i].first;
        }
        sort(L, L + n);
        int size = unique(L, L + n) - L;
        for (int i = 0; i < n; i++){
            int idx = lower_bound(L, L + size, p[i].first) - L;
            G[idx].push_back(make_pair(p[i].second, i + 1));
        }
        LL ans = 0;
        multiset<pair<LL,int>>se;
        for (int i = 0; i < size; i++){
            for (int j = 0; j < G[i].size(); j++){
                se.insert(G[i][j]);
            }
            while ((int)se.size()>k){
                se.erase(se.begin());
            }
            if ((int)se.size() == k && (se.begin()->first) >= L[i]){
                ans =max( se.begin()->first - L[i]+1,ans);
            }
        }
        printf("%I64d
", ans);
        if (ans == 0){
            for (int i = 1; i <= k; i++){
                printf("%d ", i);
            }
        }
        else{
            se.clear();
            for (int i = 0; i < size; i++){
                for (int j = 0; j < G[i].size(); j++){
                    se.insert(G[i][j]);
                }
                while ((int)se.size()>k){
                    se.erase(se.begin());
                }
                if ((int)se.size() == k&& se.begin()->first >= L[i] && (se.begin()->first - L[i] + 1) == ans){
                    for (multiset<pair<LL, int>>::iterator it = se.begin(); it != se.end(); it++){
                        printf("%d ", it->second);
                    }
                    break;
                }
            }
        }
        printf("
");
    }
//#ifdef LOCAL_TIME
//    cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
    return 0;
}
原文地址:https://www.cnblogs.com/kirito520/p/6262396.html