题目链接: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; }