zoukankan      html  css  js  c++  java
  • 1373D

    题目链接:https://codeforces.com/problemset/problem/1373/D


    题面:

    题意:给你一列数,第一个数字认为是0为偶数位,你有一次倒置一个区间字符串的机会,希望选一个区间倒置后让你统计所有偶数位的数字和最大。

    分析:不得不说cf上一些题目的质量真的高,尤其是教育场,下次一定咕咕咕

    题解:①首先你需要知道,不论起点是偶数位还是奇数位,只要倒置一段长度为奇数的区间,显然不会影响偶数位之和,所以一定是倒置一个偶数长度的区间

    ②如果倒置一个长度为2n的区间,你可以把它转化成不重叠且连续的n个长度为2的区间

    ③显然,如果只考虑区间长度为2,那显然这段区间之前的值,不会影响答案(dp的后效性),就可以用dp或者类dp的贪心。

    ④我们就记录初始数列已有的偶数位之和为sum,倒置区间后比原来多的值记录在dp数组中。(dp细节看代码)

    ⑤我们发现例如数列{a0,a1,a2}例如:1 100 2,倒置区间[0,1]的答案与倒置区间[1,2]的答案显然不同,所以左换和右换两者都要考虑,取一个max即可。

    ⑥dp是在原基础上的增加值,所以仅在偶数位操作。不妨设dp_l:dp_l[i]记录的是前i位中所有偶数位进行左换操作后,使答案增加的最优情况,dp_r同理。

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    
    inline ll read() {
        int x = 0, f = 1; char c = getchar();
        while (c<'0' || c>'9') { if (c == '-')f = -f; c = getchar(); }
        while (c >= '0' && c <= '9')x = x * 10 + c - '0', c = getchar();
        return x * f;
    }
    
    ll num[200005];
    ll dp_l[200005];//dp_l[i]记录的是前i位中所有偶数位进行左换操作后,使答案增加的最优情况
    ll dp_r[200005];//右换,前i位使答案增加的最优情况
    ll sum;//基准值
    
    int main(void)
    {
        ll t = read();
        while (t--)
        {
            sum = 0;
            ll max_ans = 0;
            ll n = read();
            for (ll i = 0; i < n; i++)
            {
                dp_l[i] = 0;
                dp_r[i] = 0;
            }
            for (ll i = 0; i < n; i++)
            {
                num[i] = read();
                if (i % 2 == 0)sum += num[i];
            }
            for (ll i = 0; i < n; i++)//左换
            {
                if (i == 0)dp_l[0] = 0;
                else if (i % 2 == 0)dp_l[i] = max(0ll, dp_l[i - 2] + num[i - 1] - num[i]);
                max_ans = max(max_ans, dp_l[i]);
            }
            for (ll i = 0; i < n; i++)//右换
            {
                if (i == 0)dp_r[1] = max(0ll, num[1] - num[0]);
                else if (i % 2 == 0)dp_r[i + 1] = max(0ll, dp_r[i - 1] + num[i + 1] - num[i]);
                max_ans = max(max_ans, dp_r[i]);
            }
            cout << max_ans + sum << endl;
        }
        return 0;
    }
  • 相关阅读:
    不是结束,而是刚刚开始
    第七次作业
    用类做封装
    用户故事
    团队编程--MP3播放器
    结对编程作业
    四则运算
    四、小电视自动抽奖
    三、wss连接B站弹幕
    一、基础设计
  • 原文地址:https://www.cnblogs.com/ZJNU-huyh/p/13502710.html
Copyright © 2011-2022 走看看