首页 > 其他分享 >Codeforces 1373 D. Maximum Sum on Even Positions 做题记录(单调队列)

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

时间:2023-01-03 00:22:15浏览次数:48  
标签:Even even int Positions Sum long 数组 odd sum

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

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

  答案要求最大化偶数位之和(但是本题中从$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);
    }
    
} 

 

标签:Even,even,int,Positions,Sum,long,数组,odd,sum
From: https://www.cnblogs.com/wegret/p/17020898.html

相关文章

  • the eleventh——2023.1.2
    scanf()函数一般只读取字符串中的一个单词,而不是一句话。例如:scanf("%s",name);printf("Hello,%s!",name) NingBabaHello,Ning!(后面的Baba在scanf这读取不到,在遇......
  • iView Dropdown events 设置点击事件无效
    一、反例<Dropdownclass="m-btn-style"style="margin-left:10px"><Buttontype="primary">......
  • C. On Number of Decompositions into Multipliers -- Codeforces
    C.OnNumberofDecompositionsintoMultipliershttps://codeforces.com/problemset/problem/397/C 思路  Codehttps://codeforces.com/contest/397/submissi......
  • UVa10827 Maximum sum on a torus
    思路一道比较经典的题目。首先我们可以把方阵扩展一下,变成\(4n^2\)大小的方阵。问题就变为在长度为\(2\timesn\)的方阵中求一个长和宽均小于等于\(n\)的子矩阵的......
  • CodeForces 1726E Tree Sum
    洛谷传送门CF传送门不错的一道Combinatorics。结论1:\(n\)为奇数时答案为\(0\)。设\(d_i\)为与点\(i\)相连的边边权乘积。每加入一条边对两端的\(d_i\)贡献......
  • P2398 GCD SUM——欧拉函数
    此题可以拓展为\(\sum\limits^n_{i=1}\sum\limits^m_{j=1}\gcd(i,j)\)结论是\(\sum\limits^{\min(n,m)}_{d=1}\varphi(d)\lfloor\dfrac{n}{d}\rfloor\lfloor\dfrac{m}{......
  • 用FreeRTOS搭建Event-Driven应用框架(转载)
    用FreeRTOS搭建Event-Driven应用框架(转载)转载网址:https://cloud.tencent.com/developer/article/1855129今天来分享一下,之前项目中使用FreeRTOS搭建的Event-Driven事件驱......
  • Sumitomo Mitsui Trust Bank Programming Contest 2019 —— B
    也不知道这比赛为啥要取这么长的名称(传送门:https://atcoder.jp/contests/sumitrust2019/tasks/sumitb2019_e哈哈,你被骗了!但网址是真的!题意有红绿蓝三种帽子RedandBl......
  • Even Subarrays(数论问题)
    题目链接题目描述:Youaregivenanintegerarray\(a_1,a_2,…,a_n(1≤a_i≤n).\)FindthenumberofsubarraysofawhoseXORhasanevennumberofdivisors.In......
  • EventLog Analyzer中的综合日志收集
    日志管理的第一步是收集日志数据。日志收集可能是一项具有挑战性的任务,因为某些系统(例如,防火墙、入侵检测系统和入侵防御系统)会生成大量日志数据的EPS(每秒事件数)。无论日志......