目的:分別從前面和後面開始找劃分點,使得前面的數字之和 = 後面的數字之和
目標表述:sum( 前面m 個數 ) = sum( 後面n個數) s.t. m+n <= N(總個數)
變形:sum[i] 表示前 i 個數之和,sum2[i]表示後 i 個數之和
如果 sum[m] == sum2[n] ,s.t., m+n <= N,問題解決!
#include <iostream>
using namespace std;
typedef long long lint;
lint a[200002] ={0};
lint sum[200002] ={0};
lint sum2[200002] ={0};
// 在 sum2[] 中搜索是否有元素= q,因爲 sum2 單調遞增,所以可以用二分查找
// 搜索範圍從 sum2[1] 到 sum2[limit]
// 返回值: 找到就返回序號,沒找到就返回 -1
int bi_search(lint q, int limit){
if( q < sum2[1] || q > sum2[limit] ) return -1;
int left = 1, right = limit, mid;
while( left <= right ){
mid = (left+right)/2;
if( sum2[left] == q ) return left;
if( sum2[right] == q ) return right;
if( sum2[mid] == q ) return mid;
if( mid == left) break;
if( sum2[mid] > q )
right = mid;
else
left = mid;
}
return -1;
}
int main()
{
int n;
cin >> n;
for(int i=1;i<=n;i++) // 從1開始
{
scanf("%lld",&a[i]);
sum[i] = sum[i-1] + a[i];
}
for(int i=n;i>=1;i--)
sum2[n+1-i] = sum2[n-i] + a[i];
/************ match ************/
lint max_gain = 0;
for(int i=1;i<n;i++){
int j = n - i; // 取值的範圍
if( bi_search(sum[i],j) != -1 )
max_gain = sum[i];
}
cout << max_gain << endl;
return 0;
}