CodeForces 732E - Sockets(优先队列)

题意: 给定 n 个插座,每个插座的电压是pi,在给定 m 个插头,每个插头的电压是qi,只有当插座的电压和插头的电压相等的时候两个才能插入。现在还有若干个减压器,在插座上插一个减压器能够使这个插座的电压变成 pi ,多个减压器可以嵌套。问在最多的插头匹配且用最少的减压器的数目。

思路:比较显然的是能匹配的尽量匹配,不能匹配时,尽量使用插减压器少的。用一个 pairint,int 来维护某个插座的当前电压和当前的减压器个数。然后从大到小遍历插头,将过大的插座的 (first,second+1) 后返回队列.直到找到第一个合适的或不合适的。直到遍历完所有的插头。

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdlib>
#include <queue>

using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int MAXN = 200000 + 10;
int cot[MAXN];
int net[MAXN];
struct node
{
    int val, num;
    int pos;
    node(int _val=0, int _num=0,int _pos=0) :val(_val), num(_num),pos(_pos){}

};

struct cmp
{
    bool operator()(const node &x, const node &y)
    {
        if (x.val != y.val)return x.val<y.val;
        return x.num > y.num;
    }
};

int main()
{
    priority_queue<node, vector<node>, cmp>pq;
    memset(cot, 0, sizeof cot);
    memset(net, 0, sizeof net);
    int n,m;
    scanf("%d%d", &n, &m);
    vector<pii>v;
    for (int i = 0; i < n; i++)
    {
        int pow;
        scanf("%d", &pow);
        v.push_back(pii(pow, i));;
    }
    sort(v.begin(), v.end(), [](const pii& x, const pii&y){return x.first < y.first; });
    for (int i = 0; i < m; i++)
    {
        int pow;
        scanf("%d", &pow);
        pq.push(node(pow, 0,i));
    }
    int maxx = 0; int minn = 0;
    for (int i = v.size() - 1; i >= 0; i--)
    {
        while (pq.size()&&pq.top().val>v[i].first)
        {
            node tmp = pq.top();
            pq.pop();
            tmp.val = ceil(tmp.val*1.0 / 2.0), tmp.num++;
            if (tmp.val == 0)continue;
            pq.push(tmp);
        }
        if (pq.size() == 0)break;
        if (pq.top().val == v[i].first)
        {
            maxx++;
            minn += pq.top().num;
            cot[pq.top().pos] = pq.top().num;
            net[v[i].second] = pq.top().pos+1;
            pq.pop();
        }
        else if (pq.top().val < v[i].first)continue;
    }
    printf("%d %d\n", maxx, minn);
    for (int i = 0; i < m; i++)
    {
        if (i)printf(" ");
        printf("%d", cot[i]);
    }
    printf("\n");
    for (int i = 0; i < n; i++)
    {
        if (i)printf(" ");
        printf("%d", net[i]);
    }
    printf("\n");
    //system("pause");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值