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
题意:
给你n个一维线段,让你求重合数>=k的区间。输出数量和各个区间。
POINT:
用扫描线来做,左端点标记为-1,右端点标记为1。遇做就cnt++,当cnt==k时记录左端点,代表答案的左端点。
右端点则--,当cnt==k时也记录,但是这两个有顺序的区别(很重要),详细看代码。
还有就是,端点重复,比如不同的线段的左端点和右端点重合了,那我们先考虑左端点,再考虑右端点,这也是为什么把左标记-1,把右标记1的原因,这样sort排序就没有问题。
pair排序就是先比first,在比second,也可以用结构体来写和排序。不过这个比较方便。
同理vector也可以用数组代替。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <map>
#include <string.h>
#include <algorithm>
#include <vector>
#include <fstream>
using namespace std;
#define lt 2*x
#define rt 2*x+1
#define LL long long
typedef pair<LL,LL> pr;
vector<pr> v;
int main()
{
LL n,k;
while(~scanf("%lld %lld",&n,&k))
{
v.clear();
for(int i=1;i<=n;i++)
{
LL l,r;
scanf("%lld %lld",&l,&r);
v.push_back(make_pair(l,-1));
v.push_back(make_pair(r,1));
}
sort(v.begin(),v.end());
int cnt=0;
vector<LL> ans;
ans.clear();
for(LL i=0;i<v.size();i++)
{
if(v[i].second==-1)
{
cnt++;
if(cnt==k)
{
ans.push_back(v[i].first);
}
}
else
{
if(cnt==k) ans.push_back(v[i].first);
cnt--;
}
}
printf("%d\n",(int)ans.size()/2);
for(LL i=0;i<ans.size()/2;i++)
{
printf("%lld %lld\n",ans[2*i],ans[2*i+1]);
}
}
return 0;
}