ZeroJudge F174: 蛋糕(Cake)

題目敘述

每筆測資第一行有兩個正整數N和K,第二行會有N個整數,分別代表蛋糕的N個區塊。要求輸出如果任意從蛋糕中切取出0~K個區塊,最大的區段和是多少 (如果取任何東西都是負的則可以不要取輸出0)。


範例輸入 #1

7 3 

3 7 -1 9 2 2 1 

範例輸出 #1

15


範例輸入 #2

5 4 

-3 -4 -5 -6 -7 

範例輸出 #2

0


範例輸入 #3

10 4 

1 -5 7 2 5 -2 6 3 0 2 

範例輸出 #3

14


範例輸入 #4

10 5 

10 -3 -5 9 -5 -6 10 7 -20 16

範例輸出 #4

17


範例輸入 #5

10 5 

10 -3 -5 9 -5 -6 10 7 -20 18

範例輸出 #5

18


解題思路

將前綴和存到陣列中之後跑For迴圈判斷每一個數字減掉前K個數字的最小值有沒有比目前最大值 (答案) 還要大,可以使用線段樹來紀錄每一個區段的最小值來防止超時。另外,在進行線段樹搜尋的時候也可以在函式中判斷目前For迴圈中跑到的數字減掉目前節點的值是否有大於答案,如果小於等於的話可以直接return函式節省時間。計算前綴和及計算答案的時候可以使用Long Long Int來防止超過範圍。

解題程式碼如下 (僅供參考):

#include <iostream>
#include <vector>
using namespace std;

long long int tree[999999] = {}, ans;
int N, K;
vector<long long int>num;

long long int max(long long int a, long long int b)
{
    if (a > b) return a;
    return b;
}

long long int build(int l, int r, int index)
{
    if (l == r)
    {
        tree[index] = num[l];
        return num[l];
    }
    long long int left = build(l, (l+r)/2, (index*2)+1);
    long long int right = build(((l+r)/2)+1, r, (index*2)+2);
    tree[index] = min(left, right);
    return tree[index];
}

long long int query(int l, int r, int cl, int cr, int index, long long int value)
{
    if (value - tree[index] < ans) return 999999999;
    if (l == cl && r == cr) return tree[index];
    if (cl == cr) return tree[index];
    if (r <= (cl+cr)/2) return query(l, r, cl, (cl+cr)/2, (index*2)+1, value);
    else if (l > (cl+cr)/2) return query(l, r, ((cl+cr)/2)+1, cr, (index*2)+2, value);
    return min(query(l, r, cl, (cl+cr)/2, (index*2)+1, value), query(l, r, ((cl+cr)/2)+1, cr, (index*2)+2, value));
}

long long int math(int l, int r, long long int value)
{
    return query(l, r, 0, N-1, 0, value);
}

long long int calc(long long int hi, int l, int r)
{
    return hi - math(l, r, hi);
}

int main() {
    cin.sync_with_stdio(0);
    cin.tie(0);
    cin >> N >> K;
    long long int count = 0;
    for (int i = 0; i<N; i++)
    {
        long long int tmp;
        cin >> tmp;
        count += tmp;
        num.push_back(count);
    }
    ans = num[0];
    long long int hi = build(0, N-1, 0);
    for (int i = 1; i<K; i++)
    {
        ans = max(ans, calc(num[i], 0, i-1));
    }
    for (int i = K; i<N; i++)
    {
        ans = max(ans, calc(num[i], i-K, i-1));
    }
    cout << max(ans, 0) << "\n";
}

留言

這個網誌中的熱門文章

ZeroJudge M933: 邏輯電路

ZeroJudge A148: You Cannot Pass?!

ZeroJudge M932: 蜜蜂觀察