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,定义一个点符合条件的是被至少k条线段覆盖到,要求找出一个最小的线段集合,这个集合能够包含所有满足那个条件的点。
(这里要注意这个线段集合中的线段不需要是之前的线段了,只要由一开始给的n条线段的端点集中的元素构成的就可以了。)
思路:
哇,这题差一点啊。。比赛的时候我也想的是左端点排序,然后是想暴力搞。。其实这题思维很好的,一个计数变量cnt,遇到一个起点就cnt++,终点就cnt--,如果遇到起点cnt变成了k,说明他是所求线段的一个起点,把他扔进答案,如果遇到了一个终点,原来是k,说明他要结束了,把他扔进答案。。哇,这种变量控制++--的我暑假的时候做到过,为什么现在想不出来呢,老了老了。。。
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 1e6 + 5;
vector <pair<int,int> > v;
int n, k;
int main()
{
while(~scanf("%d%d", &n, &k))
{
int l, r;
v.clear();
for(int i = 1; i <= n; i++)
{
scanf("%d%d", &l, &r);
v.push_back(make_pair(l,-1));
v.push_back(make_pair(r,1));
}
sort(v.begin(), v.end());
vector<int> ans;
int cnt = 0;
for(int 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", ans.size()/2);
for(int i = 0; i < ans.size(); i += 2)
{
printf("%d %d\n", ans[i], ans[i+1]);
}
}
return 0;
}