区间选点问题
Advertisement:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=21426
经典的区间选点问题,要求每个区间内的点数满足条件k个,具体做法是把右端点从小到大排序,然后每次都检查区间内的点数,如果少了,就尽量从右边开始加点,以便于和其他区间共用一点
#include"iostream"
#include"algorithm"
#include"cstring"
using namespace std;
const int maxn=1000+10;
typedef struct
{
int l,r;
}node;
bool cmp(node a1,node a2)
{
return a1.r<a2.r;
}
node a[maxn];
int book[maxn*maxn];
void swap(node &aa)
{
int temp=aa.l;
aa.l=aa.r;
aa.r=temp;
}
int main()
{
int T;
cin>>T;
while(T--)
{
int k,n;
cin>>k>>n;
int Max=-100000;
for(int i=0;i<n;i++)
{
cin>>a[i].l>>a[i].r;
if(a[i].l>a[i].r) swap(a[i]);
a[i].l+=10000;
a[i].r+=10000;
if(Max<a[i].r) Max=a[i].r;
}
sort(a,a+n,cmp);
memset(book,0,sizeof(book));
int sum=0;
for(int i=0;i<n;i++)
{
int flag=0;
for(int j=a[i].l;j<=a[i].r;j++) //每次都先检查区间是否已经满足条件
{
if(book[j]) flag++;
}
if(flag>=k) continue;
else
{
for(int j=a[i].r;j>=a[i].l&&flag<k;j--) //尽量把点放在右边
{
if(!book[j])
{
book[j]=1;
flag++;
sum++;
}
}
}
}
cout<<sum<<endl;
for(int l=0;l<=Max;l++)
if(book[l]) cout<<l-10000<<endl;
if(T) cout<<endl;
}
return 0;
}