终于AC辣,深夜一波ac,hhh~
题意:
现在有n个人,他们受到邀请去参加一个派对,然后他们会去的条件当且仅当现在已经去的人数大于等于l[i],小于等于r[i],这时他们才会答应去参加派对。要你输出最多有几个人去参加派对,并且输出它们的顺序。
思路:
一开始总是想着要以r[i]来排序,但是发现这样子贪心是有问题的。
我们首先应该sort一遍,按照r[i]来排序,然后再把当前l<=num<=r的那些满足条件的都压到优先队列里面去,然后优先队列里面是按照r从小到大来排的,因为当满足条件时,我们肯定是优先满足r小的,这样才能符合贪心的法则。
还有我一开始写挫了,导致一直wa。。。
多亏了那个神奇的第二个数据,我们在选择哪些要压进去的时候,别忘了跳过那些已经不符合情况的条件了。
#include<stdio.h>
#include<string.h>
#include<map>
#include<set>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<iostream>
using namespace std;
typedef __int64 ll;
typedef unsigned __int64 ULL;
#define inf 99999999
#define maxn 100010
int vis[maxn],ans[maxn];
struct node{
int l,r;
int idx;
friend bool operator < (node a,node b){
return a.r>b.r;
}
};
node t[maxn];
priority_queue<node> que;
bool cmp(node a,node b){
if(a.l!=b.l) return a.l<b.l;
else return a.r<b.r;
}
int main(){
int T;
while(~scanf("%d",&T)){
while(T--){
while(!que.empty()) que.pop();
int n;
memset(t,0,sizeof(t));
memset(vis,0,sizeof(vis));
memset(ans,0,sizeof(ans));
int tot=0;
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&t[i].l),t[i].idx=i;
for(int i=1;i<=n;i++) scanf("%d",&t[i].r),t[i].idx=i;
sort(t+1,t+n+1,cmp);
int num=0;
if(t[1].l!=0){
printf("0\n");
for(int i=1;i<=n;i++) printf("%d%c",i,i==n?'\n':' ');
continue;
}
que.push(t[1]);
vis[t[1].idx]=1;
int tt=2;
while(!que.empty()){
node tmp=que.top();
que.pop();
if(tmp.l<=num&&num<=tmp.r){
vis[tmp.idx]=1;
ans[tot++]=tmp.idx;
num++;
}
while(tt<=n){
if(t[tt].r<num) tt++; //这里写挫了一开始,然后一直break;
//是不对的,因为我们要跳过那些不符合条件的情况!
else if(t[tt].l<=num&&num<=t[tt].r){
que.push(t[tt]);
tt++;
}
else break;
}
}
printf("%d\n",tot);
for(int i=1;i<=n;i++){
if(!vis[i]){
ans[tot++]=i;
}
}
for(int i=0;i<tot;i++){
printf("%d%c",ans[i],i==tot-1?'\n':' ');
}
}
}
return 0;
}
/*
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
1
3
0 0 0
1 0 0
*/