[蓝桥杯][2019年第十届真题]后缀表达式(详细!)

后缀表达式又叫逆波兰式,这里是一道数据结构题
[蓝桥杯][2019年第十届真题]后缀表达式(详细!)_第1张图片

思路

易错点是以为求最大值是 单单给数排序,大的数加,小的数减。这是把减号当成减去而已。

正确的应该是:因为能加减号,所以减号的作用有 能影响其它符号的变号减去。这是核心思想
分析:

  • 其实后缀表达式是可以给加括号的,把一个负号加在用括号括起来的一坨减号的前面,就可以使得括号里所有减号变成正号。
  • 上述规则可知我们能任意地把负号调整为正号
  • 总结一下:m个减号,最大减m次(不变号),最小减1次(其余m-1次变号),因此可以选择1到m的任意减的次数。也就是说只要减号个数大于0,至少得减一次,最多所有减号做减法。
  • 然后拿负数的个数找与减号个数的关系 ,n+m+1个数,m为负号的个数,cnt为减号的个数:
    1.无减号,最简单全加起来就完事了
    2.有减号,并且全为负数时,因为最大只能改变m-1个数的符号,所以保留一个最大的负数做加法(绝对值最小),并让其余负数都变号
    3.有减号,并且不全为负数时,因为最大只能改变m-1个数的符号,所以可以把所有负数变号
    4.有减号,并且无负数时,肯定减号越少越好,故因为至少得减一次,所以把减去的机会留给最小的整数即可。

代码

import java.util.*;
public class Main {
    static Scanner in = new Scanner(System.in);
    static int n, m;
    static int[] a;
//    static int result;

    public static void main(String[] args) {
        n = in.nextInt();
        m = in.nextInt();
        int bound=m+n+1;
        int cnt=0;
        long sum=0;
        a=new int[bound];

        for (int i = 0; i <bound ; ++i) {
           a[i] = in.nextInt();
           sum+=a[i];
           if(a[i]<0) cnt++;      //计算负数个数
        }
        Arrays.sort(a);

//        不含负号
        if(m==0){
           System.out.println(sum);
           return;
        }
//        含有负号
        if(cnt!=0){    //有负数
            if(cnt!=bound) for (int i=0;i<cnt;i++) sum-=2*a[i];
            else    for (int i=0;i<cnt-1;i++) sum-=2*a[i];
        }
        else sum-=2*a[0];    //无负数

        System.out.println(sum);
    }
}

你可能感兴趣的:(蓝桥杯)