zoukankan      html  css  js  c++  java
  • Sockets CF732E set map

    题目:http://codeforces.com/problemset/problem/732/E

    题目大意:

    有n台电脑(computer)和m个插座(socket),两者均有一个power值,分别为 ai 和 bi ,只有当两者的power值相等时才可以匹配成功。当然,还有足够多个适配器(adapters)可用,插座每接一个适配器,bi 就会减半(取上整)。求最多可匹配多少电脑和插座,以及该种情况下所需要的最少的适配器数量。如有多种方案,输出其中一种即可。

    思路:

    因为这个题的输出都要用到下标(或编号),所以分别用multimap或pair存储电脑或插座的power值和对应的下标,从最小的插座power开始,匹配对应的电脑power,如果存在则记录,如果无匹配,则将插座power折半继续匹配直到值为1都未匹配成功,那么就说明该插座无论如何都无法匹配到电脑。这样可以使得当前情况下能够匹配到最大的电脑数量而且用最少的适配器,至于查找匹配自然不能遍历,可以将电脑的power存入set容器中进行find查找,效率会高一点,搜索复杂度为logN。

    代码如下:

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<utility>
     4 #include<set>
     5 #include<map>
     6 using namespace std;
     7 
     8 const int MAX = 2e5 + 2;
     9 
    10 multimap<int, int> P;           //电脑与下标对应
    11 multiset<int> S;                //存放电脑power值,用set方便查找
    12 pair<int, int> Sockets[MAX];    //插座与下标对应
    13 int RESULT1[MAX], RESULT2[MAX];
    14 
    15 int main()
    16 {
    17     int N, M, pi, si, c = 0, u = 0;
    18     cin >> N >> M;
    19     for (int i = 1; i <= N; ++i)
    20     {
    21         cin >> pi;
    22         S.insert(pi);
    23         P.insert(make_pair(pi, i));
    24     }
    25     for (int i = 1; i <= M; ++i)
    26     {
    27         cin >> Sockets[i].first;
    28         Sockets[i].second = i;
    29     }
    30     sort(Sockets + 1, Sockets + M + 1);
    31 
    32     for (int i = 1, num = 0; i <= M; ++i, num = 0)
    33         while (1)
    34         {
    35             multiset<int>::iterator set_it = S.find(Sockets[i].first);
    36             if (set_it != S.end())
    37             {
    38                 multimap<int, int>::iterator map_it = P.find(Sockets[i].first);
    39                 RESULT1[Sockets[i].second] = num;
    40                 RESULT2[(*map_it).second] = Sockets[i].second;
    41                 c++; u += num;
    42                 S.erase(set_it), P.erase(map_it);
    43                 break;
    44             }
    45             if (Sockets[i].first == 1)break;
    46             num++;
    47             Sockets[i].first = (Sockets[i].first + 1) / 2;
    48         }
    49     cout << c << " " << u << endl;
    50     for (int i = 1; i <= M; ++i)cout << RESULT1[i], i == M ? cout << endl : cout << " ";
    51     for (int i = 1; i <= N; ++i)cout << RESULT2[i], i == N ? cout << endl : cout << " ";
    52 }

    感谢您的阅读,生活愉快~

  • 相关阅读:
    有序数组中找中位数
    卡特兰数 catalan number
    海量数据等概率选取问题
    求字符串中最长无重复字符的子串
    Linux的进程通信(IPC)
    Linux多线程编程
    后缀数组处理字符串的利器
    网络编程socket基本API详解
    Windows线程的创建与终止
    《算法导论》读书笔记之第10章 基本数据结构之二叉树
  • 原文地址:https://www.cnblogs.com/lv-anchoret/p/8460879.html
Copyright © 2011-2022 走看看