zoukankan      html  css  js  c++  java
  • Jerry [动态规划]

    JerryJerry



    color{red}{正解部分}

    • 首先可以将所有相邻的正数合并在一起, 不影响答案, 且会使得数列具有性质 11: 加号之后一定是减号 .
    • 还有个非常重要的性质 22: 若两个 负号 同时出现在一起, 则除第一个负号后的数字, 后面的所有数字均可取到正值 .

    考虑从后往前去决定每个数前加不加括号,

    1. A[i]>0A[i] > 0, 括号对其无影响, F[i]=A[i]+F[i+1]F[i] = A[i] + F[i+1]
    2. A[i]<0A[i] < 0,
      1. A[i+1]<0A[i+1]<0, 根据性质22, F[i]=A[i]+suf_sum[i+1]F[i] = A[i]+suf\_sum[i+1] .
      2. A[i+1]>0A[i+1]>0, 根据性质11, 有两个决策, 分别是
        1. 不加括号得到A[i+1]A[i+1],
        2. 加括号失去A[i+1]A[i+1]但得到i+2i+2后所有数字的和;
          得到 F[i]=max(A[i]+F[i+1],A[i]A[i+1]+suf_sum[i+2])F[i] = max(A[i] + F[i+1], A[i]-A[i+1]+ suf\_sum[i+2])

    color{red}{实现部分}

    • 多组数据, cntcnt 初值 00 , suf_sum[cnt+1]=0suf\_sum[cnt+1] = 0
    • 注意 suf_sum[]suf\_sum[] 处理时需要对 A[i]A[i] 加绝对值 .
    • abs()abs()函数会炸 intint .
    #include<bits/stdc++.h>
    #define reg register
    typedef long long ll;
    
    int read(){
            char c;
            int s = 0, flag = 1;
            while((c=getchar()) && !isdigit(c))
                    if(c == '-'){ flag = -1, c = getchar(); break ; }
            while(isdigit(c)) s = s*10 + c-'0', c = getchar();
            return s * flag;
    }
    
    const int maxn = 2e5 + 10;
    
    int N;
    int cnt;
    int A[maxn];
    
    ll B[maxn];
    ll F[maxn];
    ll suf_sum[maxn];
    
    char opt[3];
    
    ll abd(ll x){ return x>0?x:-x; }
    
    void Work(){
            N = read();
            A[1] = read();
            for(reg int i = 2; i <= N; i ++){
                    scanf("%s", opt);
                    A[i] = read();
                    if(opt[0] == '-') A[i] = -A[i];
            }
            cnt = 0;
            for(reg int i = 1; i <= N; i ++){
                    B[++ cnt] = A[i];
                    while(i != N && A[i] >= 0 && A[i+1] >= 0) B[cnt] += A[++ i];
            }
            suf_sum[cnt+1] = 0;
            for(reg int i = cnt; i >= 1; i --) suf_sum[i] = suf_sum[i+1] + abd(B[i]);
            F[cnt] = B[cnt];
            for(reg int i = cnt-1; i >= 1; i --){
                    if(B[i] >= 0) F[i] = B[i] + F[i+1];
                    else if(B[i+1] >= 0) F[i] = std::max(B[i]+F[i+1], B[i]-B[i+1]+suf_sum[i+2]);
                    else F[i] = B[i] + suf_sum[i+1];
            }
            printf("%lld
    ", F[1]);
    }
    
    int main(){
            int T_ = read();
            while(T_ --) Work();
            return 0;
    }
    
  • 相关阅读:
    Java虚拟机一
    java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException
    Java虚拟机
    topcoder srm 663 div1
    topcoder srm 694 div1 -3
    topcoder srm 695 div1 -3
    topcoder srm 696 div1 -3
    topcoder srm 697 div1 -3
    topcoder srm 661 div1
    topcoder srm 698 div1 -3
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822488.html
Copyright © 2011-2022 走看看