Codeforces 1373 D. Maximum Sum on Even Positions 做题记录(单调队列)

  因为只能转一个子数组,很显然转长度为奇数的子数组,对最大化答案是没有意义的(偶数位的数字之和不会变化)。因此只考虑转偶长度的子数组。

  转动偶数长度的子数组,相当于子数组中奇位和偶位的数互换。

  答案要求最大化偶数位之和(但是本题中从$0$开始计数。为了前缀和计算的便利,我在写代码时用$1$作为开头,于是目标变成了最大化奇数位之和)。在不转动时,初始的奇数位之和是固定的一个常数。设子数组是$a[L]..a[R]$,要最大化答案中奇数位之和,相当于最大化(被奇偶调换的)子数组中偶数位和与奇数位和的差,即最大化$a[L]..a[R]$中$sum_{偶位}-sum_{奇位}$。我们只需要找到这样一个$sum_{偶位}-sum_{奇位}$最大的子数组就行了。

  开两个前缀和数组,$sum_{odd}$表示奇数位的前缀和,$sum_{even}$表示偶数位的前缀和,我们找最大的$(sum_{even}[j]-sum_{even}[i])-(sum_{odd}[j]-sum_{odd}[i])$,化简一下这个式子,化成$(sum_{even}[j]-sum_{odd}[j])-(sum_{even}[i]-sum_{odd}[i])$。

  这个式子要求最大。我们就开个数组$d$,设$d[i]=sum_{even}[i]-sum_{odd}[i]$,在$i<j$的情况下,找最大的$d[j]-d[i]$。(这里的$sum_{odd}[i]$可以不用真实地存储下来,事实上我们可以直接在读入时对$d[i]$做个伪前缀和:$i$是奇数时$d[i]=d[i-1]-a[i]$,$i$是偶数时$d[i]=d[i-1]+a[i]$。)

  找最大的$d[j]-d[i]$时,可以借助单调队列的想法,动态地求当前最小。需要注意到是子数组长度只能为偶数,因此需要对奇数位、偶数位分别做一次单调队列。

  (需要注意的是,如果最大的$sum_{偶位}-sum_{奇位}$都小于$0$,那转动就是没有意义的,不用转动。)

#include <cstdio>
#include <vector>
using namespace std;
const int maxn=2e5;

int t,n;
long long d[maxn+5];

int main(){
    scanf("%d",&t);
    while (t--){
        long long ans=0;
        scanf("%d",&n);
        d[0]=0;
        long long x;
        for (int i=1;i<=n;i++){
            scanf("%lld",&x);
            if (i%2)
                ans+=x;
            d[i]=d[i-1]+((i%2==0)?(x):(-x));
        }
        long long res=0;
        vector<long long> que;
        que.push_back(0);
        for (int i=2;i<=n;i+=2){
            while ((!que.empty())&&d[i]<d[que.back()]){
                que.pop_back();
            }
            que.push_back(i);
            if (d[i]-d[que.front()]>res)
                res=d[i]-d[que.front()];
        }
        vector<long long> q;
        for (int i=1;i<=n;i+=2){
            while ((!q.empty())&&d[i]<d[q.back()]){
                q.pop_back();
            }
            q.push_back(i);
            if (d[i]-d[q.front()]>res)
                res=d[i]-d[q.front()];
        }
        printf("%lld\n",ans+res);
    }
    
} 

 

posted @ 2023-01-03 00:09  wegret  阅读(30)  评论(0)    收藏  举报