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 ") 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 ", ans.size()); for (int i = 0; i < ans.size(); i++){ printf("%d %d ", ans[i].fi, ans[i].se); } return 0; }