做法是每次选取起始条件符合,并且结束条件最早的。(每个人的起始时间为l,结束时间为r)
#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <queue>
#include <vector>
using namespace std;
int N,T;
struct node
{
int start;
int End;
int index;
bool friend operator<(node n1,node n2)
{
return n1.End>n2.End;
}
};
bool vis[1000010];
int cmp(node a,node b) {
return a.start < b.start ;
}
node input[1000010];
vector<node> V[100010];
void slove()
{
int sum=0;
vector<int> ans;
priority_queue<node> Q;
//初始化
for(int i=0;i<N;i++)//此处应该为i小于n,不用小于等于,因为总人数只有N个时,除去自己,在自己前面接受邀请的最多只有N-1个。
{
V[i].clear();
}
//vector数组相当于二维的vector,第一维表示它的起始时间,第二维无意义。因为加入队列之后还需要按照结束时间排序。
for(int i=0;i<N;i++)
{
V[input[i].start].push_back(input[i]);
}
while(true)
{
bool flag=false;
//选取起始时间刚好符合的元素加入队列。
for(int i=0;i<V[sum].size();i++)
{
Q.push(V[sum][i]);
}
//选取一个未被访问并且结束时间最小但结束时间又大于sum(也是就是当前已经邀请到的人数)的元素
while(!Q.empty())
{
if(Q.top().End>=sum&&!vis[Q.top().index])
{
vis[Q.top().index]=true;
ans.push_back(Q.top().index);
sum++;
Q.pop();
flag=true;
break;
}
//如果没有break出去就说明没有进if语句内部,所以需要pop出去
Q.pop();
}
//如果没找到说明当前sum已经大于剩下未被选取的元素的起始时间了,所以筛选工作已经完成
if(!flag)
break;
}
cout<<sum<<endl;
if(sum)
{
printf("%d",ans[0]);
for(int i=1;i<ans.size();i++)
printf(" %d",ans[i]);
for(int i=1;i<=N;i++)
if(!vis[i])
printf(" %d",i);
cout<<endl;
}
else
{
printf("1");
for(int i=2;i<=N;i++)
if(!vis[i])
printf(" %d",i);
cout<<endl;
}
}
int main()
{
scanf("%d",&T);
//输入
while(T--)
{
memset(vis,0,sizeof(vis));
scanf("%d",&N);
for(int i=0;i<N;i++)
{
scanf("%d",&input[i].start);
input[i].index=i+1;
}
for(int i=0;i<N;i++)
{
scanf("%d",&input[i].End);
}
slove();
}
return 0;
}