Educational Codeforces Round 90 D.Maximum Sum on Even Positions

  • 題意:
    給定一個數組,設其偶數位置(0, 2, … 2k)上的元素和爲sum。我們可以對任意一個子數組,最多逆轉一次。計算能得到的最大的sum。
  • 思路
    首先我們可以想到,如果逆轉的子數組length是奇數,則不會有任何變化。
    例如 1 2 3 4,逆轉長度爲3的子數組,可以發現其sum不變。
    那麼我們便觀察,逆轉偶數長度的子數組。
    例如 7 8 4 5 7 3
    我們逆轉長度爲4的子數組——5 4 8 7 7 3,
    可以發現其sum = 5 + 8 + 7,相對於 7 + 4 + 7,變化了(8-7) + (5-4)。
    再進行觀察,逆轉長度爲6的子數組——3 7 5 4 8 7
    可以發現sum = 3 + 5 + 8, 變化了 (8-7) + (5-4) + (3-7).
    因此我們可以發現,對2*x長度的子數組進行逆轉,相當於對 x對元素進行逆轉,如上述數組 7 8,其位置是0 1,逆轉後相對位置變化,對結果做出的貢獻是8-7。這樣如果從偶數位置開始逆轉,偶數位置逆轉後成爲奇數,其相鄰的奇數位置元素逆轉成爲偶數位置,所以每對元素 對結果做出的貢獻是 a[i]-a[i-1],i from 1,i +=2 。
    如果是從奇數位置開始逆轉,如上述從8開始逆轉,其對結果做出的貢獻是a[i-1] - a[i],i from 2,i += 2。
    這樣我們可以得到兩種情況。然後每種情況得到一個 n/2取下界長度的數組nums,計算其最大連續和即可。
  • 代碼:
#include "bits/stdc++.h"
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define pb push_back
typedef long long ll;
const int maxn = 1e4 + 7;
const int INF =INT_MAX;
const double EPS = 10;
// #define _DEBUG

int main(){
#ifdef _DEBUG
    freopen("./Files/in.txt", "r", stdin);
    freopen("./Files/out.txt", "w", stdout);
#endif
    ios::sync_with_stdio(0);
    cin.tie(0);

    int t, n;
    cin>>t;
    while (t--) {
        cin>>n;
        ll ans = 0, tmp = 0;
        ll sum1 = 0, sum2 = 0;
        vector<int> a(n, 0);
        for(int i = 0;i < n;i++){
            cin>>a[i];
            if (i % 2 == 0) {
                ans += a[i];
            }
        }
        for(int i = 1;i < n;i += 2){
            sum1 = max((ll)0, a[i] - a[i-1] + sum1);
            tmp = max(tmp, sum1);
        }
        for(int i = 2;i < n;i += 2){
            sum2 = max((ll)0, a[i-1] - a[i] + sum2);
            tmp = max(tmp, sum2);
        }
        ans += tmp;
        cout<<ans<<endl;
    }
    return 0;
}

如第一個循環,a[i]-a[i-1]即nums的值,sum每次加上它,如果小於0,則取sum = 0,也即重新計算連續和。每次tmp更新爲最大的sum。
其基本思想就和dp取最大連續和一樣。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章