优先对列模拟 hdu5437 Alisha’s Party

传送门:点击打开链接

题意:有许多人带有权值的礼物来拜访公主,公主会在第ti个人到的时候把门打开瞬间,放ki个人进来,其中进来的顺序是权值最大的先进,如果权值一样大就先来的先进。当人全部到齐后会再次开门让所有人都进来。

思路:先将开门的时间读入然后排序,然后模拟将n个人都插入到优先对列中,然后离线维护答案,最后输出即可

#include<map>
#include<set>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define fuck printf("fuck")
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)
using namespace std;
typedef long long LL;

const int MX = 150000 + 5;

string name[MX];
struct Data {
    int value, id;
    bool operator<(const Data &b)const {
        if(b.value == value) return id > b.id;
        return value < b.value;
    }
} A[MX];

struct Que {
    int Begin, num;
    bool operator<(const Que &b)const {
        return Begin < b.Begin;
    }
} Q[MX];

int ans[MX];
char word[300];

int main() {
    int T, n, m, q; //FIN;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d%d", &n, &m, &q);
        for(int i = 1; i <= n; i++) {
            scanf("%s%d", word, &A[i].value);
            name[i] = string(word);
            A[i].id = i;
        }
        for(int i = 1; i <= m; i++) {
            scanf("%d%d", &Q[i].Begin, &Q[i].num);
        }
        sort(Q + 1, Q + 1 + m);

        int tot = 0, cur = 1;
        priority_queue<Data>work;
        for(int i = 1; i <= n; i++) {
            while(cur <= m && i == Q[cur].Begin + 1) {
                int size = min((int)work.size(), Q[cur].num);
                for(int j = 1; j <= size; j++) {
                    Data f = work.top();
                    work.pop();
                    ans[++tot] = f.id;
                }
                cur++;
            }
            work.push(A[i]);
        }
        while(!work.empty()) {
            Data f = work.top();
            work.pop();
            ans[++tot] = f.id;
        }

        for(int i = 1; i <= q; i++) {
            int id;
            scanf("%d", &id);
            printf("%s%c", name[ans[id]].c_str(), i == q ? '\n' : ' ');
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值