[Title] Psionic transmission (greedy algorithm, blue bridge cup)

[Title] Psionic transmission (greedy algorithm, blue bridge cup)

This time we look at a topic, the last one from the 10th Blue Bridge Cup C/C++ and Java Group B provincial competition.

Since the topic is a bit long, only part of the topic is shown here.

Insert picture description here
Insert picture description here

As shown in the figure, at the end of the question, it reminds us that the input volume of the question is relatively large, and it needs to be read in quickly. If you are a Java player, we'd better write a quick input class to avoid timeouts.
Insert picture description here

According to the scope of the data in this question, you may need to write a long type and int type data input method in the fast input class.
code show as below:

class JavaIn {
    
    
    static private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static private StringTokenizer sti = null;
    //long数组快速输入
    public static void in(long[] arr)  {
    
    
        int len = arr.length;
        //这里特殊处理一下,从1开始输入
        for (int i = 1; i < len; i++) {
    
    
            arr[i] = nextLong();
        }
    }
    public static String next() {
    
    
        while (sti == null || !sti.hasMoreTokens()) {
    
    
            try {
    
    
                sti = new StringTokenizer(br.readLine());
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
        return sti.nextToken();
    }
    public static long nextLong() {
    
    
        return Long.parseLong(next());
    }
    
    public static int nextInt(){
    
    
        return Integer.parseInt(next());
    }
}

Using this method for input and output is more efficient than the Scanner class, but the disadvantage is that it can only read data such as letters or numbers. Of course, it is suitable for this question, but for other topics, you need to pay attention to the type of data input.

Let’s start to analyze this question. The question is relatively long, but the core content of the question needs to be grasped: "Formally speaking, it is ai−1+=ai,ai+1+=ai,ai−=2ai" and "minimal instability" "These two sentences, such as the first one of the first test case, "5, -2, 3", (ai-1 = 5, ai+1 = 3, ai = -2), according to the operation of the title Later, it became:

a[i-1] = 5+(-2) = 3

a[i+1] = 3 +(-2) = 1

a[i] = -2-(-2)*2 = 2

This is the explanation of the first example. This group of cases is quite special. There are only 3 high-level templars. If there are more, then we will not be able to handle it well.

This requires some prefix and some knowledge.

The prefix sum is the sum of all the elements of another array before an array records a certain subscript, that is, assuming that the array a = [0,1,2];
its prefix and the array b satisfy, b[0] = a[ 0] = 0, b[1] = a[0] + a[1] = 2…

Of course this is just a one-dimensional prefix sum. For this problem, we can only understand one-dimensional.

Going back to this question, using the prefixes and knowledge we have just learned, we set the array a, which is the prefix sum of the psionic powers of the high-level templars in the question, to s, then s[i-1] = a[0 ] +… + A[i-1]; s[i] = a[0] +… + a[i]; s[i+1] = a[0] +… + a[i+1].
The special s[0] = a[0]

It is not difficult to find that the first test case has reminded us that if we sort all a, we need to make the maximum of the absolute value of the difference between all the prefixes and the adjacent two to be the smallest.

The following is the complete code implementation (some details are in the comments):

import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;

public class T10_灵能传输 {
    
    
    public static void main(String[] args) {
    
    
        int T;
        T = JavaIn.nextInt();
        while (T-- != 0) {
    
    
            int n = JavaIn.nextInt();
            long[] a = new long[n + 1];
            //前缀和
            long[] s = new long[n + 1];
            long ans = 0;
            JavaIn.in(a);
            s[0] = 0;
            for (int i = 1; i <= n; i++) {
    
    
                s[i] = s[i - 1] + a[i];
            }
            long s_0 = s[0];
            long s_n = s[n];
            if (s_0 > s_n) {
    
    
                long t = s_0;
                s_0 = s_n;
                s_n = t;
            }
            Arrays.sort(s);
            for (int i = 0; i <= n; i++) {
    
    
                if (s_0 == s[i]) {
    
    
                    s_0 = i;
                    break;
                }
            }

            for (int i = 0; i <= n; i++) {
    
    
                if (s_n == s[i]) {
    
    
                    s_n = i;
                    break;
                }
            }
            //建立标记数组,避免处理奇偶问题
            boolean[] marks = new boolean[n + 1];
            int leftPtr = 0;
            int rightPtr = n;
            //储存传递完的灵能
            long[] ss = new long[n + 1];
            //跳着取
            for (int i = (int) s_0; i >= 0; i -= 2) {
    
    
                ss[leftPtr++] = s[i];
                //标记
                marks[i] = true;
            }

            for (int i = (int) s_n; i <= n; i += 2) {
    
    
                ss[rightPtr--] = s[i];
                //标记
                marks[i] = true;
            }

            for (int i = 0; i <= n; i++) {
    
    
                //没被标记的就存储起来
                if (!marks[i]) {
    
    
                    ss[leftPtr++] = s[i];
                }
            }
            for (int i = 1; i <= n; i++) {
    
    
                ans = Math.max(ans, Math.abs(ss[i] - ss[i - 1]));
            }
            System.out.println(ans);
        }

    }
}


class JavaIn {
    
    
    static private BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static private StringTokenizer sti = null;
    //long数组快速输入
    public static void in(long[] arr) {
    
    
        int len = arr.length;
        //这里特殊处理一下,从1开始输入
        for (int i = 1; i < len; i++) {
    
    
            arr[i] = nextLong();
        }
    }
    public static String next() {
    
    
        while (sti == null || !sti.hasMoreTokens()) {
    
    
            try {
    
    
                sti = new StringTokenizer(br.readLine());
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }
        return sti.nextToken();
    }
    public static long nextLong() {
    
    
        return Long.parseLong(next());
    }
    public static int nextInt() {
    
    
        return Integer.parseInt(next());
    }
}

Results after submission: In
Insert picture description here
summary, some strategies for this topic are really hard to think about. I am more culinary, and I can write it by referring to the ideas of the big guys.

Guess you like

Origin blog.csdn.net/m0_55418284/article/details/114237334