Codeforce - 1006C -Three Parts of the Array(前缀和(后缀和)+ 二分 ) + upper_bound和lower_bound用法

题目链接:http://codeforces.com/problemset/problem/1006/C

题意

给定一长度为n的数组,将其划分为A,B,C三段(每一段都能为空),求A段之和与C段之和相等的前提下,求其和的最大值。

                                                                                                                                                                                            

题解

用两个数组分别保存前缀和 与 后缀和。利用二分查找(第一次用了暴力查找超时了)进行寻找最优解。利用函数进行二分查找。

因为前缀和是递增的,所以枚举后缀和在前缀和中查找,如果能找到其相等且使A C两段不重合,则可保存下来,以此求得最大值。谨记注意数据范围.long long.(不然会WA)

upper_bound和lower_bound用法

  • headfile是algorithm,工作原理是二分查找。

  • 函数作用

      iterator lower_bound( const key_type &key ): 返回一个迭代器,指向键值>= key的第一个元素。

      iterator upper_bound( const key_type &key ):返回一个迭代器,指向键值> key的第一个元素。

  • lower_bound的作用:lower_bound的返回值减去数组的地址就是要查找的元素在数组中的位置。
  •    两个函数的用法类似,在一个左闭右开有序区间里进行二分查找,需要查找的值由第三个参数给出。
        对于upper_bound来说,返回的是被查序列中第一个大于查找值的指针,也就是返回指向被查值>查找值的最小指针,lower_bound则是返回的是被查序列中第一个大于等于查找值的指针,也就是返回指向被查值>=查找值的最小指针。
        不过除此之外,这两个函数还分别有一个重载函数,可以接受第四个参数。如果第四个参数传入greater<Type>(),其中Type改成对应类型,那么upper_bound则返回指向被查值<查找值的最小指针,lower_bound则返回指向被查值<=查找值的最小指针。
        最后说一点使用的注意事项,先看这么一句话“ The elements in the range shall already be sorted according to this same criterion (operator< or comp), or at least partitioned with respect to val”(引用自http://www.cplusplus.com/reference/algorithm/upper_bound/)。简单来说,如果你用上述两个函数三个参数的那种形式,记得那个左闭右开的区间要为非递减的顺序,如果你给第四个参数传入greater<Type>(),则区间为非递增的顺序。
  • 函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置,且last的位置是越界的!!返回查找元素的第一个可安插位置,也就是“元素值>=查找值”的第一个元素的位置

  • eg:

    举例如下:(有序数组)

    一个数组number序列为:4,10,11,30,69,70,96,100.设要插入数字3,9,111.pos为要插入的位置的下标

    pos = lower_bound( number, number + 8, 3) - number,pos = 0.即number数组的下标为0的位置。

    pos = lower_bound( number, number + 8, 9) - number, pos = 1,即number数组的下标为1的位置(即10所在的位置)。

    pos = lower_bound( number, number + 8, 111) - number, pos = 8,即number数组的下标为8的位置(但下标上限为7,所以返回最后一个元素的下一个元素)。

  • 借鉴博客(链接):                                                                            https://blog.csdn.net/yexiaohhjk/article/details/44968847                             https://blog.csdn.net/u011008379/article/details/50725670                                                           http://lib.csdn.net/article/cplusplus/35797        

  • AC Code

    #include <iostream>     
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = 2e5+5;
    typedef long long LL;
    int n, d[MAXN];
    LL pre[MAXN], suf[MAXN];
    int main()
    {
        scanf("%d", &n);
        for(int i=0; i<n; i++) 
    	{
    		scanf("%d", &d[i]);
    	} 
        pre[0] = d[0];
        for(int i=1; i<n; i++) 
        {
        	pre[i] = d[i] + pre[i-1];
        }
        suf[n-1] = d[n-1];
        for(int i=n-2; i>=0; i--)
        {
        	suf[i] = d[i] + suf[i+1];
        }
        LL ans = 0;
        for(int i = 0; i < n; i++)
        {
            int pos = lower_bound(pre, pre+n, suf[i])-pre;
    //        printf("%d\n",pos);
            if (pos < i && pre[pos] == suf[i])
            {
                ans = max(ans, suf[i]);
                break;
            }
        }
        cout<< ans <<endl;
        return 0;
    }

               

猜你喜欢

转载自blog.csdn.net/Alibaba_lhl/article/details/81091894