k个区间相交的段落数 Educational Codeforces Round 4 D

http://codeforces.com/contest/612/problem/D

 

题目大意:给你n个区间,这n个区间会有相交的部分,如果一个区间相交的部分>=k,那么就把这个区间记录下来。且要求所记录的区间个数尽量少(换句话说就是区间尽量大),问有几个这样的区间,并且输出这样的区间。

思路一:

我之前的想法就是把所有的sort出来,然后用树状数组来求区间相交个数。但是这样子写出来以后可能会出现这样的区间,即[1,3][3,5],所以我们又要把这两个区间合并一下,所以合并的时候有需要使用线段树来合并区间。理论上来说,这样子是可行的,就是太麻烦了。

于是接下来是官方题解。

 

思路二:

我们把所有的元素预处理出来以后sort,然后我们发现题干所需要求的是>=k即可,那么我们可以发现,区间如果要是最长的话,那么必然是cnt=k的时候,所以我们只需要在sort以后,O(n)去获得这个cnt即可。在[left, right]为left的时候cnt++,right的时候cnt--,然后统计一下cnt==k的时候就能够得到最大的区间了。

//看看会不会爆int!数组会不会少了一维!
//取物问题一定要小心先手胜利的条件
#include <bits/stdc++.h>
using namespace std;
#pragma comment(linker,"/STACK:102400000,102400000")
#define LL long long
#define ALL(a) a.begin(), a.end()
#define pb push_back
#define mk make_pair
#define fi first
#define se second
#define haha printf("haha\n")
const int maxn = 1e6 + 5;
int n, k;
pair<int, int> p[maxn];
vector<pair<int, int> > ve;
int a[maxn];

int main(){
    cin >> n >> k;
    for (int i = 1; i <= n; i++){
        int l, r; scanf("%d%d", &l, &r);
        ve.push_back(mk(l, 0));
        ve.push_back(mk(r, 1));
        p[i] = mk(l, r);
    }
    sort(ALL(ve));
    vector<pair<int, int> > ans;
    int cnt = 0, tmp;
    for (int i = 0; i < ve.size(); i++){
        int ty = ve[i].se;
        int val = ve[i].fi;
        if (ty == 0){
            cnt++;
            if (cnt == k){
                tmp = val;
            }
        }
        if (ty == 1){
            if (cnt == k){
                ans.pb(mk(tmp, val));
            }
            cnt--;
        }
    }
    printf("%d\n", ans.size());
    for (int i = 0; i < ans.size(); i++){
        printf("%d %d\n", ans[i].fi, ans[i].se);
    }
    return 0;
}
View Code

 

posted @ 2016-12-11 23:28  知る奇迹に  阅读(273)  评论(0)    收藏  举报