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
补上昨天的博客,昨天网断了,一直连不上。
开始学习扫面线,这个题是个扫描线初级的题。
题目的意思是说每条线段以l,r的形式给你,让你求出至少覆盖k次的区间,我们利用扫描线的特性,想象从左至右有一条竖着的线我们扫过去,遇见左短点则加一,遇见右端点则减一,这样我们就求出来了至少被覆盖了k次的区间。
注:这个题不可用cin,会超时。
扫描线与其说是一个算法,不如说是一个思想,我们想象一条线,从左至右或者从下到上的扫一遍,至于区间线段树和扫描线的组合我还不会,继续加油!
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <algorithm>
#define LL long long
using namespace std;
int main(){
LL n,k;
vector<pair<LL,LL> >vec;
vector<LL>ans;
cin>>n>>k;
for(LL i=0;i<n;i++){
LL a,b;
scanf("%I64d%I64d",&a,&b);
vec.push_back(make_pair(a,-1));
vec.push_back(make_pair(b,1));
}
sort(vec.begin(),vec.end());
int cnt=0;
LL h=vec.size();
for(LL i=0;i<h;i++){
if(vec[i].second==-1){
cnt++;
if(cnt==k)
ans.push_back(vec[i].first);
}
else{
if(cnt==k)
ans.push_back(vec[i].first);
cnt--;
}
}
int len=ans.size();
cout<<len/2<<endl;
for(int i=0;i<len/2;i++){
cout<<ans[i*2]<<" "<<ans[i*2+1]<<endl;
}
return 0;
}