hdu(5360)——Hiking

终于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
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值