题意:beta想要请n个soda去远足,邀请第i个soda时要符合一个条件:当前人数不少于li并且不大于ri(如果满足就同意,即使后来的人数会不符合现在提出的条件),问最多可以邀请多少个soda,输出数目和邀请顺序(若有多种方法输出任一个即可)
思路:将soda按照l的值从小到大排列(如果soda【0】!= 0则能邀请的人数为0),每次将符合当前条件的soda(l值不大于当前已参加的人数)放进优先队列(优先队列按照ri从小到大),然后取出队列里符合条件:r >= 当前已参加人数并且r值较小的那个soda(即为最优)。
把参见的soda从数组的前面开始放,不参加的从后面开始放即可,最后输出
#include <stdio.h>
#include <algorithm>
#include <queue>
#define maxn 1000010
using namespace std;
struct node
{
int l;
int r;
int id;
bool operator<(const node &a) const {
return r > a.r;
}
}soda[maxn];
bool cmp(node a, node b)
{
if(a.l != b.l) return a.l < b.l;
return a.r < b.r;
}
int ans[maxn];
int main()
{
int n, t, i, now, s, e;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(i = 0;i < n;i++)
{
scanf("%d", &soda[i].l);
soda[i].id = i + 1;
}
for(i = 0;i < n;i++)
scanf("%d", &soda[i].r);
sort(soda, soda + n, cmp);
priority_queue<node> q;
now = 0, i = 0, s = 0, e = n- 1;
if(soda[0].l != 0)
{
printf("%d\n", now);
for(i = 0;i < n;i++) printf("%d%c", i+1, i==n-1?'\n':' ');
continue;
}
for(;i < n&&soda[i].l <= now;i++) q.push(soda[i]);
while(!q.empty())
{
while(!q.empty())
{
if(q.top().r >= now)
{
now++;
ans[s++] = q.top().id;
q.pop();
break;
}
else ans[e--] = q.top().id;
q.pop();
}
for(;i < n&&soda[i].l <= now;i++){
q.push(soda[i]);
//printf("%d\n", soda[i].id);
}
}
for(;i < n;i++) ans[e--] = soda[i].id;
printf("%d\n", now);
for(i = 0;i < n;i++) printf("%d%c", ans[i], i==n-1?'\n':' ');
}
return 0;
}