• CodeForces 1373D. Maximum Sum on Even Positions(最大连续子段和)


    题目:你被给予了一个n个整数的数组a。数组的下标从0开始。你可以逆置一个数组的子数组(连续的)最多一次,你的任务是使得这个数组的偶数位置的数字的和最大。

    分析:奇数长度的子数组翻转并不会改变偶数位置的数字,因此,我们只需要考虑长度为偶数的子区间。偶数长度的子数组我们有两种情况,一种是偶数位置开始,奇数位置结束,另一种是奇数位置开始,偶数位置结束。我们先考虑第一种情况,我们要求出一个子区间翻转的收益,我们存储每个位置的(a[i + 1] - a[i]),i从0开始,每次+2,我们要求出一个连续子段和的最大值,这可以联想到DP-最大连续子段和,对于一个位置的数,如果前缀和 <= 0,那么对于当前的数来说,加上这个前缀不会使得收益变大,因此我们重新令前缀和统计为0。这样两种情况求出后,我们加上这个收益,就是答案。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    using LL = long long;
    const int N = 200005;
    int a[N];
    int main()
    {
    	int t;
    	scanf("%d", &t);
    
    	while (t--)
    	{
    		int n;
    		scanf("%d", &n);
    
    		LL sum = 0;
    
    		for (int i = 0; i < n; ++i)
    		{
    			scanf("%d", &a[i]);
    			if ((i & 1) == 0) sum += a[i];
    		}
    
    		LL mx = 0;
    		LL diff1 = 0;
    		//偶开头
    		for (int i = 0; i + 1 < n; i += 2)
    		{
    			diff1 += a[i + 1] - a[i];
    			diff1 = max(0LL, diff1);
    			mx = max(mx, diff1);
    		}
    
    		LL diff2 = 0;
    
    		for (int i = 1; i + 1 < n; i += 2)
    		{
    			diff2 += a[i] - a[i + 1];
    			diff2 = max(0LL, diff2);
    			mx = max(mx, diff2);
    		}
    
    		printf("%lld
    ", sum + mx);
    	}
    
    
    	return 0;
    }
    
    
  • 相关阅读:
    为什么LIKELY和UNLIKELY要用两个叹号
    vuex-persist数据持久化存储插件
    【ejabberd】安装XMPP服务器ejabberd(Ubuntu 12.04)
    Dynamics CRM2013 picklist下拉项行数控制
    jdk1.8新日期时间类(DateTime、LocalDateTime)demo代码
    webpack插件解析:HtmlWebpackPlugin是干什么的以及如何使用它
    marked实现
    Vue组件使用、父子组件传值
    VUE启动报错
    nodejs创建vue项目
  • 原文地址:https://www.cnblogs.com/pixel-Teee/p/13229768.html
Copyright © 2020-2023  润新知