首页 > 试题广场 >

小美的陡峭值操作

[编程题]小美的陡峭值操作
  • 热度指数:780 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
定义一个数组的的陡峭值为:相邻两个元素之差的绝对值之和。
现在小美拿到了一个数组,她可以最多进行1次操作:选择一个区间,使得区间内所有元素加1。
小美希望最终数组的陡峭值尽可能小,你能帮帮她吗?

输入描述:
第一行输入一个正整数t,代表询问次数。
对于每次询问输入两行:
第一行输入一个正整数n,代表数组长度。
第二行输入n个正整数a_i,代表小美拿到的数组。
1\leq t \leq 1000
2\leq n \leq 10^5
1\leq a_i \leq 10^9
保证所有询问的n的总和不超过10^5


输出描述:
输出t行,输出一个整数,代表该次查询陡峭值的最小值。
示例1

输入

2
5
1 4 2 3 4
3
1 2 1

输出

5
1

说明

第一组询问,选择[3,4]区间即可,数组变成{1,4,3,4,4}。
第二组询问,选择[1,1]区间即可,数组变成{2,2,1}。
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int t = in.nextInt();
        while(t--!=0){
            int n = in.nextInt();
            long[] a = new long[n+1];
            //输入的时候顺便计算原本的陡峭值,(tips:操作后陡峭值的变化一共只有三种情况:1.减二  2.减一   3.不变)
            long sum = 0;
            for(int i=1;i<=n;i++){
                a[i] = in.nextLong();
                if(i == 1)continue;
                sum+=Math.abs(a[i] - a[i-1]);
            }
            //设置标志位,看看有符合这样条件的区间:[l,r] (l-1位置比l位置大)&&(r位置比r+1位置小)
            int l = -1,r = -1;
            for(int i =1;i<n;i++){
                //只找最左侧的
                if(l == -1 && a[i] > a[i+1])l = i+1;
                //只找最右侧的
                if(a[i] < a[i+1])r = i;
            }
            //分情况讨论
            if(l == -1 && r== -1)System.out.println(sum);
            else if(l!= -1 && r!= -1 && l <= r)System.out.println(sum-2);
            else System.out.println(sum-1);
        }
    }
}

发表于 2025-08-08 13:19:37 回复(0)
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int t = sc.nextInt();
        while (t-- > 0) {
            int n = sc.nextInt();
            int[] a = new int[n];
            for (int i = 0; i < n; i++) {
                a[i] = sc.nextInt();
            }
            System.out.println(calculateMinSteepness(a));
        }
        sc.close();
    }

    private static long calculateMinSteepness(int[] a) {
        int n = a.length;
        if (n == 1) return 0;

        // 计算原始陡峭值
        long original = 0L;
        for (int i = 0; i < n - 1; i++) {
            original += Math.abs(a[i] - a[i + 1]);
        }

        long maxReduction = 0L;

        // 检查所有可能的单元素区间
        for (int i = 0; i < n; i++) {
            long reduction = 0L;
            if (i > 0) {
                reduction += Math.abs(a[i - 1] - a[i]) - Math.abs(a[i - 1] - (a[i] + 1));
            }
            if (i < n - 1) {
                reduction += Math.abs(a[i] - a[i + 1]) - Math.abs((a[i] + 1) - a[i + 1]);
            }
            maxReduction = Math.max(maxReduction, reduction);
        }

        // 检查所有可能的连续区间
        for (int l = 0; l < n; l++) {
            for (int r = l; r < n; r++) {
                if (r - l + 1 > 10) break; // 限制区间长度,防止超时
                long reduction = 0L;
                if (l > 0) {
                    reduction += Math.abs(a[l - 1] - a[l]) - Math.abs(a[l - 1] - (a[l] + 1));
                }
                if (r < n - 1) {
                    reduction += Math.abs(a[r] - a[r + 1]) - Math.abs((a[r] + 1) - a[r + 1]);
                }
                maxReduction = Math.max(maxReduction, reduction);
            }
        }

        return original - maxReduction;
    }
}
发表于 2025-06-07 18:38:02 回复(0)