image.png

    1. #include <iostream>
    2. #include <map>
    3. #include <algorithm>
    4. #include <cstring>
    5. using namespace std;
    6. int main()
    7. {
    8. int n;
    9. cin >> n;
    10. int power, id;
    11. map<int, int> mp;
    12. map<int, int>::iterator p;
    13. mp[1000000000] = 1;
    14. while (n--)
    15. {
    16. cin >> id >> power;
    17. p = mp.lower_bound(power); //查找第一个大于等于的值
    18. if (p == mp.end()) //没有大于等于power的
    19. p--;
    20. int t = abs(p->first - power);
    21. int ansID = p->second;
    22. if (p != mp.begin()) //不用while,因为map容器里面没有实力值相等的
    23. {
    24. p--;
    25. if (abs(p->first - power) < t || (abs(p->first - power) == t && p->second < ansID))
    26. ansID = p->second;
    27. }
    28. cout << id << " " << ansID << endl;
    29. p = mp.find(power); //在容器中查找实力值和power相等的,如果查找到了 就比较它们的id,将id小的放在里面。
    30. if (p->second > id || p == mp.end())
    31. mp[power] = id;
    32. }
    33. return 0;
    34. }

    这个题目其实是上一个题目的翻版(没有放出),改动主要在于,之前的题目要求任意两人的实力值不同,且最后输出时如果有两个人与这个人的实力差相同,则选择实力弱的那个(毕竟大家都喜欢虐人不喜欢被虐)。所以前一个题目我用的是set
    这个题目一开始想用multiset,因为看到了两人的实力值可以相同。但其实有一种更简单的方法,是使用map来做,键(first)为实力值,值(second)为id。这难道不是违反题目中两个人id可以相同的规定么?
    其实不然,使用map完全是因为题设中输出的要求:如果最后有两个候选人(上面说的实力差相等),则输出id小的那个。既然这然,我们就可以在插入一个新的成员时,如果map中已经有人的实力值与新插入的这个相同,那就谁的id小就用谁的id,毕竟最后如果实力差相同了,也只会用到最小的那个id。也就是说,如果两个人的实力值相同的话,以后也就id小的那个人会用来比较(id大的那个人连成为工具人的机会都没有了),那就干脆不用存这个id大的人儿了呗!
    当然,用实力值最为键是首先就要想到的,毕竟调用 lower_bound 这种函数的时候是要使用“<”运算符比较的