区间覆盖问题.数轴上有n个闭区间[ai,bi],选择尽量少的区间覆盖一条指定一条线段[s,t]。
例题:https://vjudge.net/problem/UVA-10020
选择尽量少的区间覆盖[0,m]
题解:
把各个区间按照起点从小到大排序。
如果第一个区间大于0,无解。因为其他区间的起点更大,不可能覆盖到0.
预处理,去掉[0,m]区间外的区间。
每次选择起点小于start的最长区间,选择完之后更新区间。
最后需判断最后一次的start是否大于等于M,否则清空操作。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+100;
typedef long long LL;
typedef pair<LL,LL> p;
p seg[maxn];
vector<p> vec;
vector<p> ans;
int M;
void solve()
{
int siz = vec.size();
int i;
int ll=0;
int index=-1;
int start=0;
for(i=0;i<siz;i++)
{
if(vec[i].first<=start)
{
if(vec[i].second>ll)
{ll=vec[i].second;index=i;}
}
else if(index!=-1)
{
ans.push_back(vec[index]);
start = vec[index].second;
i--;
}
}
if(index!=-1&&start<M){
ans.push_back(vec[index]);
start=vec[index].second;
}
if(start<M) ans.clear();
}
bool cmp(p a,p b)
{
return a.first<b.first;
}
int main()
{
int T;
cin>>T;
while(T--)
{
cin>>M;
int i=0;
int l,r;
while(scanf("%d%d",&l,&r))
{
if(l==0&&r==0) break;
seg[i].first=l;
seg[i].second=r;
i++;
}
sort(seg,seg+i,cmp);
/*for(int j=0;j<i;j++)
{
cout<<seg[j].first<<" "<<seg[j].second<<endl;
}*/
if(seg[0].first>0) {cout<<0<<endl;if(T) cout<<endl;continue;}
/*预处理*/
for(int j=0;j<i;j++)
{
if(seg[j].second<0||seg[j].first>M) continue;
vec.push_back(seg[j]);
}
solve();
cout<<ans.size()<<endl;
for(int k=0;k<ans.size();k++)
{
cout<<ans[k].first<<" "<<ans[k].second<<endl;
}
vec.clear();
ans.clear();
}
return 0;
}