• CodeForces


    题目:https://codeforces.com/problemset/problem/1038/D

    题意:给你n个数字,每个数字可以吃左右两边的数,然后吃完后自己变成 a[i]-a[i+1]或者a[i]-a[i-1],然后问你最后只剩一个数的时候最大可能的值是多少

    思路:我们首先想是由哪一个数会留到最后,那他肯定会吃掉左边的数和右边的数,而如果要使当前数字尽量大,那么就要使左右两边的数字尽量小,我们要确定左边右边的数字尽量小的话,因为有负数的关系,我们每一步都要记录当前格子从左到右的最大值和最小值,然后同理再记录一个从右到左的,然后枚举哪一个留到最后,减去前缀最小和后缀最小即可

    #include<bits/stdc++.h>
    #define maxn 500005
    #define mod 1000000007
    using namespace std;
    typedef long long ll;
    ll n,a[maxn];
    ll dp1[maxn][2];
    ll dp2[maxn][2];
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        int q;
        dp1[n][0]=a[n];dp1[n][1]=a[n];
        dp2[1][0]=a[1];dp2[1][1]=a[1];
        for(int i=n-1;i>=2;i--){
            dp1[i][0]=max(max(a[i]-dp1[i+1][1],a[i]+dp1[i+1][0]),dp1[i+1][0]-a[i]);
            dp1[i][1]=min(min(a[i]-dp1[i+1][0],a[i]+dp1[i+1][1]),dp1[i+1][1]-a[i]);
        }
        for(int i=2;i<=n-1;i++){
            dp2[i][0]=max(max(a[i]-dp2[i-1][1],a[i]+dp2[i-1][0]),dp2[i-1][0]-a[i]);
            dp2[i][1]=min(min(a[i]-dp2[i-1][0],a[i]+dp2[i-1][1]),dp2[i-1][1]-a[i]);
        }
        ll mx=a[1]-dp1[2][1];
        for(int i=2;i<=n;i++){
            mx=max(mx,a[i]-dp1[i+1][1]-dp2[i-1][1]);
        }
        cout<<mx;
    }
    /*
    5
    -14 -2 0 -19 -12
    47
    */
  • 相关阅读:
    箭头函数和普通函数的区别是什么?
    前端如何优化网站性能?
    instanceof原理
    call、apply区别
    函数的节流和防抖
    关于this的指向性问题
    undefined 和null的区别?
    浅谈堆和栈的理解?
    关于vue中watch和computed
    简单说一下什么是回流和重绘
  • 原文地址:https://www.cnblogs.com/Lis-/p/11396298.html
Copyright © 2020-2023  润新知