You are given n segments on the coordinate axis Ox and the number k. The point is satisfied if it belongs to at least k segments. Find the smallest (by the number of segments) set of segments on the coordinate axis Ox which contains all satisfied points and no others.
The first line contains two integers n and k (1 ≤ k ≤ n ≤ 106) — the number of segments and the value of k.
The next n lines contain two integers li, ri ( - 109 ≤ li ≤ ri ≤ 109) each — the endpoints of the i-th segment. The segments can degenerate and intersect each other. The segments are given in arbitrary order.
First line contains integer m — the smallest number of segments.
Next m lines contain two integers aj, bj (aj ≤ bj) — the ends of j-th segment in the answer. The segments should be listed in the order from left to right.
3 2
0 5
-3 2
3 8
2
0 2
3 5
3 2
0 5
-3 3
3 8
1
0 5
题目大意:如果一个点被至少k条线段所覆盖,那么他是满足条件的一个点,输出这些点所构成的线段集合。
用cnt记录当前点被覆盖次数,只有在扫描到题目所给线段的左端点或者右端点时会引起cnt的变化。
如果扫到左端点,意味着当前点有可能成为一段新区间的左端点,如果扫到右端点,意味着当前点可能成为一段新区间的右端点。
那么就排完序之后扫一遍。
如何排序呢?只以当前点坐标排序显然是不行的,因为会导致一些只有一个点构成的区间被忽略,还会导致一些完整区间被分成两段。
所以我们需要使得左端点优先级高于右端点,这样可以避免以上两种情况。(手动模拟一下就可以理解了)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<bits/stdc++.h> using namespace std; const int inf=2e6+10; struct seg{ int x; int d; seg(){} seg(int a,int b){ x=a;d=b; } bool operator < (const seg & o)const { return x<o.x||(x==o.x&&d>o.d); } }a[inf]; int n,k; int b[inf],ans; int main() { // freopen("1.txt","r",stdin); scanf("%d%d",&n,&k); n<<=1; for(int i=1;i<=n;i++){ int x; scanf("%d",&x); a[i]=seg(x,i&1); } sort(a+1,a+n+1); int cnt=0; for(int i=1;i<=n;i++){ if(a[i].d==1){ cnt++; if(cnt==k)b[++ans]=a[i].x; } else { if(cnt==k)b[++ans]=a[i].x; cnt--; } } printf("%d\n",ans/2); for(int i=1;i<ans;i+=2){ printf("%d %d\n",b[i],b[i+1]); } return 0; }