CodeForces 732E Sockets 【贪心】【STL】

题目:点击打开链接

题意:有n台电脑,m个插座,每台电脑的功率是p_i,每个插座哦的功率是s_i,只有当p_i=s_i时,电脑和插座才能连起来。有种变压器,能将插座的功率减半并向上取整,并且变压器能连接使用,求最多能有几台电脑连接上插座,当台数最多时,取变压器最少的情况,输出连接成功的电脑个数,变压器使用个数,每个插座使用变压器的数目,每台电脑连到哪个插座,若不连接输出零。

分析:对于同一台电脑,如果有多个插座接上不相同的变压器都能连接,要取s_i最小的那个插座,因为大的插座可能还可以满足于其他电脑,且使用的变压器数目少,所以要从插座s_i小的开始枚举,看是否有没有满足功率相同的电脑,满足则保存答案,若不能满足则插座功率每次都除以二取上界,直到功率为一以后还不满足则循环,枚举下一个插座,直到枚举完所有的插座。我们可以用STL中的multiset记录每台电脑的功率,multimap记录每种功率对应的电脑编号,插座功率与电脑功率相同时,将记录从multiset和multimap中删除,注意各STL函数的返回值,set的find函数返回迭代器,count函数返回数目,multimap是用pair储存的。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#include <map>
#define sqr(x) ((x)*(x))
#define PR pair<int,int>
#define MP make_pair
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
const ll INF = (1ULL<<63)-1;
const int inf=0x3f3f3f3f;
const int M=100010;
const int N=200010;
const ll MOD=1000000007;
const double eps=1e-3;
const double pi=acos(-1.0);
using namespace std;
PR com[N],soc[N];
multiset<int> s;
multiset<int>::iterator sit,spos;
multimap<int,int> mp;
multimap<int,int>::iterator mit,mpos;
int n,m,u,c;
int a[N],b[N];
int main()
{
    int i,j;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&com[i].fi);
        com[i].se=i;
        s.insert(com[i].fi);
        mp.insert(MP(com[i].fi,i));
    }
    for(i=1;i<=m;i++)
    {
        scanf("%d",&soc[i].fi);
        soc[i].se=i;
    }
    sort(soc+1,soc+1+m);
    for(i=1;i<=m;i++)
    {
        int sum=0;
        while(1)
        {
            spos=s.find(soc[i].fi);
            if(spos!=s.end())
            {
                mpos=mp.find(soc[i].fi);
                a[soc[i].se]=sum;
                b[(*mpos).se]=soc[i].se;
                c++;
                u+=sum;
                s.erase(spos);
                mp.erase(mpos);
                break;
            }
            if(soc[i].fi==1) break;
            sum++;
            soc[i].fi=(soc[i].fi+1)/2;
        }
    }
    printf("%d %d\n",c,u);
    for(i=1;i<=m;i++)printf("%d ",a[i]);puts("");
    for(i=1;i<=n;i++)printf("%d ",b[i]);puts("");
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值