牛客_选区间

选区间
https://www.nowcoder.com/practice/70cd4744404a4fbcbffe69e53e1f964c

import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

public class Main {
    private static int N;
    private static int[] dp;

    public static void main(String[] args){
        Scanner in = new Scanner(System.in);

        while(in.hasNext()){
            // solution1(in);
            solution2(in);
        }
    }

    /**
     * 模拟法: 单调栈
     * @param in
     */
    private static void solution1(Scanner in){
        N = in.nextInt();

        int[] nums = new int[N+1];
        for(int i=1; i<=N; i++){
            nums[i] = in.nextInt();
        }

        Map<Integer, Integer> rightMap = new HashMap<Integer, Integer>();
        Map<Integer, Integer> leftMap = new HashMap<Integer, Integer>();
        Deque<Integer> rightStack = new ArrayDeque<Integer>();
        Deque<Integer> leftStack = new ArrayDeque<Integer>();
        int num;
        for (int i=N; i>=1; i--){
            // 找到当前元素右边第一个小于当前元素的元素索引 N+1:表示没找到, 当前元素右边都比当前元素大
            num = nums[i];
            while (!rightStack.isEmpty() && num<=nums[rightStack.peek()]){
                rightStack.pop();
            }
            rightMap.put(i, rightStack.isEmpty() ? N+1 : rightStack.peek());
            rightStack.push(i);

            // 找到当前元素左边第一个小于当前元素的元素索引 0:表示没找到, 当前元素左边都比当前元素大
            num = nums[N-i+1];
            while (!leftStack.isEmpty() && num<=nums[leftStack.peek()]){
                leftStack.pop();
            }
            leftMap.put(N-i+1, leftStack.isEmpty() ? 0 : leftStack.peek());
            leftStack.push(N-i+1);
        }
        
        dp = new int[N+1];
        for(int i=1; i<=N; i++){
            dp[i] = dp[i-1] + nums[i];
        }

        long result = 0;
        for(int i=1; i<=N; i++){
            result = Math.max(result, (long) nums[i] * (dp[rightMap.get(i)-1]-dp[leftMap.get(i)]));
        }

        System.out.println(result);
    }

    /**
     * 模拟法: 循坏遍历
     * @param in
     */
    private static void solution2(Scanner in){
        N = in.nextInt();

        int[] nums = new int[N+1];
        for(int i=1; i<=N; i++){
            nums[i] = in.nextInt();
        }

        dp = new int[N+1];
        for(int i=1; i<=N; i++){
            dp[i] = dp[i-1] + nums[i];
        }

        long result = 0;
        for(int i=1; i<=N; i++){
            result = Math.max(result, compute(nums, i));
        }

        System.out.println(result);
    }

    private static long compute(int[] nums, int i){
        int left = i-1;
        int right = i+1;

        // 找到当前元素左边第一个小于当前元素的元素索引 0:表示没找到, 当前元素左边都比当前元素大
        while(left>0 && nums[i]<=nums[left]){
            left--;
        }

        // 找到当前元素右边第一个小于当前元素的元素索引 N+1:表示没找到, 当前元素右边都比当前元素大
        while(right<=N && nums[i]<=nums[right]){
            right++;
        }

        return (long) nums[i] * (dp[right-1]-dp[left]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值