A1044 Shopping in Mars (25 分| 二分查找| upper_bound,附详细注释,逻辑分析)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_24452475/article/details/100549437

写在前面

  • 思路分析
    • 理解题意
      • For each test case, print i-j in a line for each pair of i ≤ j such that Di + ... + Dj = M. Note that if there are more than one solution, all the solutions must be printed in increasing order of i.
        • 恰好等于
      • If there is no solution, output i-j for pairs of i ≤ j such that Di + ... + Dj >M with (Di + ... + Dj −M) minimized.
        • 不能恰好等于,付出最少价格(总和必须⼤大于等于所给值)
    • 简单模拟,2个超时。
    • 后来sum数组递增,改用⼆分法查找
      • 即sum[i]表示1~i的所有数字的总和~
  • 题目有难度,活灵活用ing

测试用例

  • input:
    16 15
    3 2 1 5 4 6 8 7 16 10 15 11 9 12 14 13
    
    output:
    1-5
    4-6
    7-8
    11-11
    
    input:
    5 13
    2 4 5 7 9
    
    output:
    2-4
    4-5
    

ac代码

  • #include <vector>
    #include <iostream>
    using namespace std;
    
    vector<int> sum, result;
    int n, m;
    void binary_searchs(int i, int &j, int &tmpsum)
    {
        int left = i, right = n;
        while(left < right)
        {
            int mid = (left + right)/2;
            if(sum[mid] - sum[i-1] >= m)
                right = mid;
            else
                left = mid + 1;
        }
        j = right;
        tmpsum = sum[j] - sum[i-1];
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        sum.resize(n+1);
        for(int i=1; i<=n; i++)
        {
            scanf("%d", &sum[i]);
            sum[i] += sum[i-1];
        }
        int minans = sum[n];
        for(int i=1; i<=n; i++)
        {
            int j, tmpsum;
            binary_searchs(i, j, tmpsum);
            if(tmpsum > minans) continue;
            if(tmpsum >= m)
            {
                if(tmpsum < minans)
                {
                    result.clear();
                    minans = tmpsum;
                }
                result.push_back(i);
                result.push_back(j);
            }
        }
    
        for(int i=0; i<result.size(); i+=2)
            printf("%d-%d\n", result[i], result[i+1]);
    
        return 0;
    }
    

学习代码

  • 题意分析
    • 给出1个数字序列与1个数S,在数字序列中求出所有和值为S的连续子序列(区间下标左端点小的先输出,左端点相同时右端点小的先输出)。
    • 若没有这样的序列,求出和值恰好大于S的子序列(即在所有和值大于S的子序列中和值最接近S)
    • 半懂状态,有时间多调试、可自行实现1把
      在这里插入图片描述
    #include<iostream>
    #include<algorithm>
    #define MAX 100001
    using namespace std;
    
    int diamonds[MAX];
    int main()
    {
        int N,M,input;
        while(cin>>N>>M)
        {
            int minlost = 99999999;
            int low = 0;
            bool notFound = true;
            fill(diamonds,diamonds+MAX,0);
    
            for(int i=1; i<=N; i++)
            {
                cin>>diamonds[i];
                diamonds[i]+=diamonds[i-1];
                while(diamonds[i] - diamonds[low]>M)
                {
                    minlost = min(minlost,diamonds[i] - diamonds[low]);
                    low++;
                }
                if(diamonds[i] - diamonds[low] == M)
                {
                    cout<<low+1<<"-"<<i<<endl;
                    notFound = false;
                }
            }
            if(notFound)
            {
                low = 0;
                for(int i=1; i<=N; i++)
                {
                    while(diamonds[i] - diamonds[low]>minlost)
                        low++;
                    if(diamonds[i] - diamonds[low]==minlost)
                    {
                        cout<<low+1<<"-"<<i<<endl;
                    }
                }
            }
        }
        return 0;
    }
    

知识点小结

  • lower_bound( begin,end,num)
    • lower_bound( begin,end,num,greater<type>() )
    • 第1个大于等于num的数字,能发挥数字地址
    • 不存在返回end
  • upper_bound( begin,end,num)
    • upper_bound( begin,end,num,greater<type>() )
    • 第1个大于num的数字
    • 不存在返回end
  • 代码示例1
  • // lower_bound/upper_bound example
    #include <iostream>
    #include <algorithm>
    #include <vector>
    using namespace std;
    
    int main ()
    {
        int myints[] = {10,20,30,30,20,10,10,20};
        vector<int> v(myints,myints+8);           // 10 20 30 30 20 10 10 20
        vector<int>::iterator low,up;
    
        sort (v.begin(), v.end());                // 10 10 10 20 20 20 30 30
    
        low=lower_bound (v.begin(), v.end(), 20); //          ^
        up= upper_bound (v.begin(), v.end(), 20); //                   ^
    
        cout << "lower_bound at position " << int(low- v.begin()) << " " <<  myints[int(low- v.begin())+1] << endl;
        cout << "upper_bound at position " << int(up - v.begin()) << " " << myints[int(up- v.begin())+1] << endl;
    
        return 0;
    }
    

猜你喜欢

转载自blog.csdn.net/qq_24452475/article/details/100549437