4 8 4 1 3 2 2 1 0 3 5 3 6 4 2 1 7 6 8 3 3 2 0 5 0 3 6 4 5 2 7 7 6 7 6 8 2 2 3 3 3 0 0 2 7 4 3 6 3 2 2 5 8 5 6 5 3 3 1 2 4 6 7 7 6 5 4 3 5
7 1 7 6 5 2 4 3 8 8 4 6 3 1 2 5 8 7 7 3 6 7 1 5 2 8 4 0 1 2 3 4 5 6 7 8
题意:现在有n个人等待邀请,但是第i个人可以被邀请的要求是邀请他的时候,已经邀请的人不少于ai个且不多于bi个。当一个人被邀请之后不会反悔离开。
求最多邀请的人数,以及邀请的顺序(邀请了不来也得写上)
很简单很明确的一个贪心。
首先按每个人至少的要求排序。每次把当前达到最少要求的人取出来放入优先队列,然后每次抉择的时候按至多要求的人数最小的开始邀请即可。
下面贴代码。
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <map>
#include <queue>
#include <vector>
#include <iostream>
#include <algorithm>
#define moo 1000000007//10^9+7
#define PI acos(-1.0)
#define eps 1e-5
using namespace std;
struct People
{
int Min,Max,id;
}peo[100000+10];
bool operator <(People x,People y)
{
return x.Max>y.Max;
}//优先队列内以至多值从小到大排序
bool cmp(People x,People y)
{
return x.Min<y.Min;
}
priority_queue<People>Q;
vector<int>ans;
int main()
{
int T;
cin>>T;
while(T--)
{
while(!Q.empty())
Q.pop();
ans.clear();
int n;
scanf("%d",&n);
for(int i=1;i<=n;peo[i].id=i,i++)
scanf("%d",&peo[i].Min);
for(int i=1;i<=n;i++)
scanf("%d",&peo[i].Max);
sort(peo+1,peo+n+1,cmp);
int cnt=0,use=1;//cnt存已经成功邀请的人,use未达到最小值的当前的人
do
{
if(!Q.empty())
{
if(Q.top().Max>=cnt)
cnt++;
ans.push_back(Q.top().id);
Q.pop();
}//首先判断当前队列首的人会不会已经超过了上限,
for(;use<=n;use++)//判断当前人的最小值是否被满足,如果满足,就加入优先队列
if(peo[use].Min<=cnt)
Q.push(peo[use]);
else
break;
}while(!Q.empty());//当队列为空说明不会有人再满足最小值了
int flag=0;
cout<<cnt<<endl;
for(int i=0;i<ans.size();flag=1,i++)//按顺序输出满足过最小值的人
printf(flag==0?"%d":" %d",ans[i]);
for(;use<=n;flag=1,use++)//将未满足最小值的人输出
printf(flag==0?"%d":" %d",peo[use].id);
printf("\n");
}
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文:http://blog.csdn.net/zip_fan/article/details/47340287