C.Minimum Array(二分+set)

题目描述:

知识点:

lower_bound和uper_bound

lower_bound(起始地址,结束地址,要查找的数值) 返回的是数值 第一个 出现的位置。

upper_bound(起始地址,结束地址,要查找的数值) 返回的是数值 最后一个 出现的位置。

binary_search(起始地址,结束地址,要查找的数值)  返回的是是否存在这么一个数,是一个bool值

lower_bound(val):返回容器中第一个值【大于或等于】val的元素的iterator位置。

upper_bound(val): 返回容器中第一个值【大于】val的元素的iterator位置

使用:

 1 int low=lower_bound(t.begin(),t.end(),5)-t.begin(); 2 int upp=upper_bound(t.begin(),t.end(),5)-t.begin(); 

 

思路:

题目是说要让数组a的每一位与b中某一位相加取余后最小,找规律可得

a              对应b的“最好选择元素”的优先级为

0              0  1  2  ...  n-1

1   n-1  0  1  ...  n-2  

2        n-2  n-1  0  ...  n-3 

...

n-1     1  2  3  ...  0

刚开始做法是真的列了一个大数组从0到200000,读入b的时候就直接把数字存到index对应的位置,如b[n]=n,然后根据不同的a[i]遍历整个b数组,结果超时

第二次把不用b那么大的数组,b中只存b[i],对b排序,对每个a[i]遍历b数组,因为b中对应a[i]最优先的数应为n-a[i]。在b中查找,如果找到,数字用掉并标记为-1;若没找到,按算法应返回的是不超过b的最后一个元素,此时将位置+1即可选取到次优先的a[i]对应的数,当然要选择大于等于0的数,即为使用的。结果超时

第三次不用标记-1,改用listr直接remove,想着是删除元素list应该比vector要快一点,结果超时

第四次想到既然排好序了,二分吧,刚好可以用lower_bound符合语义。结果超时

最后上网搜题解,用multiset的lower_bound,要更快。。。好像set的内部实现是平衡二叉树,所以更快?

不过最后提醒了我,既然排好序了,就该想到二分来提速(O(log n)),而不是傻傻的遍历一遍又一遍(O(n)).

下面是代码:

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <vector>
 4 #include <set>
 5 #define max_n 200005
 6 using namespace std;
 7 int n;
 8 vector<int> a;
 9 multiset<int> b;
10 
11 int main()
12 {
13     cin >> n;
14     int nums;
15     for(int i = 0;i<n;i++)
16     {
17         cin >> nums;
18         a.push_back(nums);
19     }
20     for(int i = 0;i<n;i++)
21     {
22         cin >> nums;
23         b.insert(nums);
24     }
25     for(auto i = a.begin();i!=a.end();i++)
26     {
27         int num = n-*i;
28         //cout << "num " << num << endl;
29         set<int>::iterator j;
30         //for(j = b.begin();*j<num&&j!=b.end();j++);
31         j = b.lower_bound(num);
32         if(j!=b.end()&&(*j==num||*j>num))
33         {
34             *i = (*i+*j)%n;
35         }
36         else if(j==b.end())
37         {
38             j=b.begin();
39             *i=(*i+*j)%n;
40         }
41         //cout << "b " << b[j] << endl;
42         b.erase(j);
43     }
44     for(auto i = a.begin();i!=a.end();i++)
45     {
46         cout << *i << " ";
47     }
48     return 0;
49 }
原文地址:https://www.cnblogs.com/zhanhonhao/p/11213831.html