题意:给定n个人,现在要邀请这些人去远足,但每个人同意邀请的条件是当前已经同意去远足的人数c必须满足c>=l[i]&&c<=ri,问你邀请的顺序是什么才能使尽可能多的人去远足,若有多个最优解,输出任意的一个。
思路:很容易想到,在左值满足的情况下找最小的右值。但是N<=10^5 所以 姿势要好。
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <string.h>
#include <map>
#include <set>
using namespace std;
#define maxn 100005
#define inff 1<<30
struct node1
{
int ri,li,id;
friend bool operator <(node1 x,node1 y)
{
return (x.ri>y.ri);
}
}a[maxn];
bool cmp(node1 x,node1 y)
{
return x.li<y.li;
}
int v[maxn],c[maxn];
int main()
{
int t,n,i;
scanf("%d",&t);
while(t--)
{
priority_queue<node1>q;//优先队列是按照右值小排序的
scanf("%d",&n);
for( i=1;i<=n;i++)
{
scanf("%d",&a[i].li);
a[i].id=i;
}
for( i=1;i<=n;i++)
{
scanf("%d",&a[i].ri);
}
sort(a+1,a+1+n,cmp);//按照左值小排序
int ans=0;
memset(v,0,sizeof v);
int k=1;
int j=1;
for( i=1;i<=n;i++)
{
while(j<=n&&a[j].li<=ans)//每次加入符合的li的数
{
q.push(a[j]);
j++;
}
while(!q.empty())
{
node1 tp=q.top();
q.pop();
if(tp.ri>=ans)//找出符合的右值,找到就break 队列中还有其他数
{
c[k++]=tp.id;
v[tp.id]=1;
ans++;
break;
}
}
}
for(i=1;i<=n;i++)
{
if(!v[i]){
c[k++]=i;
}
}
printf("%d\n",ans);
for(i=1;i<k;i++)
{
if(i!=1)printf(" ");
printf("%d",c[i]);
}
printf("\n");
}
return 0;
}