快手2019校招筆試題

目的:分別從前面和後面開始找劃分點,使得前面的數字之和 = 後面的數字之和

目標表述: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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章