• 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 }
  • 相关阅读:
    字体大小(几号-几磅
    基于有限差分的偏移方法与基于相移方法的区别
    ubuntu aptget install problem
    su安装
    石油、天然气、地质类投稿刊物及邮箱
    ubuntu添加中文输入法
    C#使用Quartz.NET详细讲解
    Using Developer Dashboard in SharePoint 2010
    Windows Server AppFabric 使用
    列出联接和投影
  • 原文地址:https://www.cnblogs.com/zhanhonhao/p/11213831.html
Copyright © 2020-2023  润新知