题目: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 }
感谢您的阅读,生活愉快~