zoukankan      html  css  js  c++  java
  • 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
    */
  • 相关阅读:
    错误页面提示大全
    http协议基础知识
    初识性能测试
    seo
    测试工程师的分类和发展方向
    Jsessionid和cookie的区别与联系
    nginx配置
    复盘能力
    开发自测方法
    OKR 目标关键成果法
  • 原文地址:https://www.cnblogs.com/Lis-/p/11396298.html
Copyright © 2011-2022 走看看