「Codeforces」B. Avoid Local Maximums

B. Avoid Local Maximums

https://codeforces.com/contest/1635/problem/B

题目描述

你有一个数组,数组中的每一个元素都是整形数值( 1 ≤ a i ≤ 1 0 9 1\leq a_i \leq 10^9 1ai109 ),你可以多次对数组进行操作,每次操作你都可以使用一个大小为 1 ≤ x ≤ 1 0 9 1 \leq x \leq10^9 1x109 之间的任意数字替换数组中的 a i a_i ai

求:使用最少的操作,使数组内不包含局部最大值。

局部最大值:若 a i a_i ai 大于相邻的两个元素,则它就是局部最大值。

输入描述

每个测试包含多个测试用例。 第一行将包含一个整数 t (1≤t≤10000)——测试用例的数量。 然后是 t 个测试用例。

每个测试用例的第一行包含一个整数 n (2≤n≤2⋅105) — 数组 a 的大小。

每个测试用例的第二行包含 n 个整数 a1,a2,…,an (1≤ai≤109),数组的元素。

保证所有测试用例的 n 之和不超过 2⋅105。

输出描述

对于每个测试用例,首先输出一个包含单个整数 m 的行——所需的最小操作数。 然后输出一行由 n 个整数组成的行——操作后的结果数组。 请注意,此数组应该与初始数组的 m 个元素完全不同。

如果有多个答案,打印任何一个。

样例

#1

5
3
2 1 2
4
1 2 3 1
5
1 2 1 2 1
9
1 2 1 3 2 3 1 2 1
9
2 1 3 1 3 1 3 1 3
0
2 1 2
1
1 3 3 1
1
1 2 2 2 1
2
1 2 3 3 2 3 3 2 1
2
2 1 3 3 3 1 1 1 3

在第一个示例中,数组不包含局部最大值,因此我们不需要执行操作。

在第二个示例中,我们可以将 a2 更改为 3,则数组没有局部最大值。

提示

解析

讲真,虽然过了,不过就是做法好像比较笨(不管,反正我过了,哈哈哈)。

 1 2 3 1 // 3 是局部最大值
 1 3 3 1 // 更新前面的 2 变成 3
 
 1 2 1 2 1 // 两个 2 都是局部最大值
 1 2 2 2 1 // 修改中间的 1 为 2(执行一次)
 1 1 1 1 1 // 修改两个 2 为 1(执行两次)

根据局部最大值的定义,可以知道局部最大值若有多个,一定是相隔开的,两两之间至少隔了一个元素,那么我们只需要让这个元素修改为左右两边最大的那一方就可以啦。

AC Code

import java.util.*;
import java.io.*;

public class Main {
    
    
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StreamTokenizer st = new StreamTokenizer(br);
    static PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));

    public static void main(String[] args) throws Exception {
    
    
        int T = nextInt();
        while(T-- != 0) {
    
    
            int n = nextInt();
            int[] A = new int[n];
            boolean[] vis = new boolean[n];
            for(int i = 0; i < n; i++) A[i] = nextInt();
            for(int i = 1; i < n - 1; i++) {
    
     // 筛选局部最大值
                if(A[i] > A[i-1] && A[i] > A[i+1]) {
    
    
                    vis[i] = true;
                }
            }
            int total = 0; // 统计执行次数
            for(int i = 1; i < n - 1; i++) {
    
     // 修改局部最大值
                if(i + 2 < n && vis[i] && vis[i+2]) {
    
     // 若两个局部最大值相隔一格,则修改中间元素
                    total++;
                    A[i + 1] = Math.max(A[i], A[i + 2]);
                    vis[i] = false;
                    vis[i + 2] = false;
                    continue;
                }
                if(vis[i]){
    
     // 单个局部最大值
                    total++;
                    A[i-1] = A[i];
                    vis[i] = false;
                }
            }
            out.println(total);
            for(int i = 0; i < n; i++) out.print(A[i] + " ");
            out.println();
        }
        out.flush();
    }

    public static int nextInt() throws Exception {
    
    
        st.nextToken();
        return (int) st.nval;
    }

    public static String nextStr() throws Exception {
    
    
        st.nextToken();
        return st.sval;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43098197/article/details/130481499
今日推荐