Codeforces Round #407 (Div. 2) C.Functions again(789C)

題目鏈接:http://codeforces.com/problemset/problem/789/C

題目大意:對於N個數,選定其中的【L,R】的數,
使得|a[l+1]-a[l]|-|a[l+2]-a[l+3]|+….+|a[r-1]-a[r-2]|-|a[r]-a[r-1]|最大;
其實就是每兩個數做差,得到一個n-1長度的序列b,然後對序列b的【L,R】區間裏,從L開始數第一項以及後面的奇數項都是加,第二項以及後面的偶數項都是減。在這樣的條件下求出最大值。

思路:分成兩種情況,對於新構造的序列b,一種是選擇的區間裏,L是奇數,另一種就是L是偶數了。
不難看出,如果選擇的L是奇數,那麼在進行累加的時候,偶數項都應該是減掉,也就是隻要對序列b的偶數項都乘上一個-1之後,用一維DP的思路求最大連續子序列和(Max Sum ,詳情參考hdu1003),得出一個最大值,然後把奇數項乘上-1,偶數項變回原狀,再求一次Max Sum,取兩者之間的較大值即可。

簡單說下hdu1003,也就是最大連續子序列和;
用dp的思路將,dp【i】應該是保存【1,i】這個區間裏,以i爲結尾的最大連續子序列和;
而對於dp【i+1】來說,如果dp【i】>0,那麼dp[i+1]=dp[i]+a[i+1];否則,dp[i+1]=a[i+1];因爲前綴比0小,加上反而會變少。然後可以發現,每次DP的過程,並不需要用到之前的dp[i-2]的數據,所以連數組都不用開,直接用一個變量sum記錄一個累加和,一旦sum小於0就從0開始繼續累加就好。

注意:數據爆int,需要longlong

AC代碼:

#include<bits/stdc++.h>

using namespace std;

typedef long long LL;

inline LL absi(LL n)
{
    if(n<0)
        return -n;
    return n;
}


LL road[100005];

int main()
{
    int n;
    cin>>n;
    for(int i=0 ; i<n ; i++)
    {
        cin>>road[i];
    }
    LL maxi=0;
    LL save=0;
    for(int i=1 ; i<n ; i++)
    {
        road[i-1]=absi(road[i-1]-road[i]);
        maxi=max(road[i-1],maxi);
    }
    for(int i=0 ; i<n-1 ; i++)
    {
        if(i%2!=0)
            road[i]*=-1;
    }
    for(int i=0 ; i<n-1 ; i++)
    {
        save+=road[i];
        if(save<0)
        {
            save=0;
        }
        maxi=max(maxi,save);
    }
    for(int i=0 ; i<n-1 ; i++)
    {
        road[i]*=-1;
    }
    save=0;
    for(int i=0 ; i<n-1 ; i++)
    {
        save+=road[i];
        if(save<0)
        {
            save=0;
        }
        maxi=max(maxi,save);
    }
    cout<<maxi<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章