hdu5360--Hiking(优先队列)

题目链接:点击打开链接

题目大意:邀请n个人去旅游,给出每个人同意邀请时对人数的限制条件:最小人数和最大人数,一旦接收邀请就不会再退出,求一个序列,在这个序列中可以邀请到最多的人去旅游。

首先对n个人的最小人数限制由小到大排序,记录当前已经接受邀请的人数,然后将满足最小人数的人加入优先队列,优先队列按照最大人数由小到大排列,每次吐出的都是最大人数限制的最小值,如果当前的人数小于等于最大的人数就可以邀请到,否则就邀请不到。每当接受邀请的人数增加,就循环一次,直到所有人都遍历完。

#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std ;
struct node{
    int s , e , id ;
    bool operator < (node a) const {
        return e > a.e ;
    }
}p[100010] , q ;
priority_queue <node> que ;
int vis[100010] ;
vector<int> vec ;
int cmp(node a,node b) {
    return a.s < b.s ;
}
int main() {
    int t , n , i , j , num ;
    scanf("%d", &t) ;
    while( t-- ) {
        while( !que.empty() ) que.pop() ;
        memset(vis,0,sizeof(vis)) ;
        vec.clear() ;
        scanf("%d", &n) ;
        for(i = 0 ; i < n ; i++) {
            scanf("%d", &p[i].s) ;
            p[i].id = i+1 ;
        }
        for(i = 0 ; i < n ; i++)
            scanf("%d", &p[i].e) ;
        sort(p,p+n,cmp) ;
        num = 0 ; i = 0 ;
        for(j = 0 ; j < n ; j++) {
            while( i < n ) {
                if( p[i].s <= num ) {
                    que.push(p[i]) ;
                    i++ ;
                }
                else break ;
            }
            while( !que.empty() ) {
                if( que.top().e >= num ) {
                    vec.push_back( que.top().id ) ;
                    vis[ que.top().id ] = 1 ;
                    que.pop() ;
                    num++ ;
                    break ;
                }
                else
                    que.pop() ;
            }
        }
        int cnt = 0 ;
        printf("%d\n", vec.size()) ;
        for(i = 0 ; i < vec.size() ; i++) {
            cnt++ ;
            if( cnt == n )
                printf("%d\n", vec[i]) ;
            else
                printf("%d ", vec[i]) ;
        }
        for(i = 1 ; i <= n ; i++) {
            if( vis[i] ) continue ;
            cnt++ ;
            if( cnt == n )
                printf("%d\n", i) ;
            else
                printf("%d ", i) ;
        }
    }
    return 0 ;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值