【算法】第三届全国大学生算法设计与编程挑战赛(冬季赛)

7题金,6题银,5题铜

【参考:2021-2022年度第三届全国大学生算法设计与编程挑战赛(冬季赛)题解_int 我的博客-CSDN博客】

【参考:2021-2022年度第三届全国大学生算法设计与编程挑战赛 【部分题题解】_辉小歌的博客-CSDN博客】

签到题:模拟,程序填空(I题)
容易题:E、G、K

练习网址:
http://vj.saikr.com/contest/20/problem/D D为题目序号

题目列表:http://vj.saikr.com/contest/20/problems

B: Error

【算法】第三届全国大学生算法设计与编程挑战赛(冬季赛)_第1张图片
思路:二分

import java.util.Scanner;

// 参考:https://blog.csdn.net/m0_58177653/article/details/123773699
public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        int[] a = new int[n];
        for (int i = 0; i < n; i++) {
            a[i] = sc.nextInt();
        }
        int low = 0;
        int high = Integer.MAX_VALUE;
        int result = -1;
        while (low <= high) {
            int mid = low + (high - low) / 2;
            if (check(mid, a)) {
                // 存在,要求求最小的eps,缩小右区间
                result = mid;
                high = mid - 1;
            } else {
                low = mid + 1;
            }
        }
        System.out.println(result);
    }

    // 存在题目要求的序列b_i 返回true 否则为false
    // b_i为上升正整数序列,对于任意i都有|a_i-b_i|<=eps
    public static boolean check(int eps, int[] a) {
        int n = a.length;
        int b = Math.max(1, a[0] - eps); // b_0
//        System.out.println(b);
        for (int i = 1; i < n; i++) {
            if (a[i] + eps < b + 1) // b_i+1至少为b_i+1
                return false; // 二者差值大于eps

            else { // a[i]和b_i+1 二者差值<= eps
                // b_i+1至少为b_i+1, b_i+1最小为a[i]-eps 二者取最大值
                b = Math.max(b + 1, a[i] - eps);
//                System.out.println(b);
            }
            // a:7 9 5 1 3 2
            // b:1 3 4 5 6 7
        }
        return true;
    }


}

n = int(input())
a = [int(i) for i in input().strip().split()]
l=0
r = max(a)-min(a)
result =0
def check(mid):
    b = max(a[0]-mid,1)
    for i in a[1:]:
        if i+mid<b+1:
            return False
        else:
            b=max(b+1,i-mid)
    return True
while l<=r:
    mid =int((l+r)/2)
    if check(mid):
        result = mid
        r = mid-1
    else:
        l = mid+1

print(result)

D: 树的果实 不会

【参考:saikr oj | 树的果实】

好像是区间查询,但和树在一起就不会了

E: 吃利息(签到题)

【参考:saikr oj | 吃利息】

【算法】第三届全国大学生算法设计与编程挑战赛(冬季赛)_第2张图片

简单模拟题

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int k = sc.nextInt();
        int n = sc.nextInt();
        int result = k;

        for (int i = 1; i <= n; i++) {
            int x = result / 10;
            // 利息
            if (x >= 5)
                result += 5;
            else
                result += x;

            result += 5;
        }
        System.out.println(result);
    }
}

F:Star

【参考:saikr oj | F:Star】
凸包

G: MP4

【参考:saikr oj | MP4】
【参考:第三届全国大学生算法设计与编程挑战赛 (冬季赛)部分题解_容艾的博客-CSDN博客】

Input
一行一个数字 n, 表示存在的视频个数


Output
一共 50 行,每行一个字符串,分别为字典序第 i 小的视频文件名,注意,这个文件名里需要包含 .mp4

暴力法,超时 大概能到1000000

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        String[] arr = new String[n];
        for (int i = 0; i < n; i++) {
            arr[i] = String.valueOf(i+1);
        }
        // 字典序排序
        Arrays.sort(arr, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });

        for (int i = 0; i < 50; i++) {
            System.out.println(arr[i]+".mp4");
        }
    }
}

【参考:2021-2022年度第三届全国大学生算法设计与编程挑战赛(冬季赛)G. MP4_NEFU AB-IN的博客-CSDN博客】

dfs爆搜即可

  • dfs(l, r, k) 表示边界为l,r,找k个
  • 举个例子n = 100 n = 100n=100
  • 优先考虑大的数,所以10倍扩大范围(因为0是最优的),直到不能扩了,如1 , 10 , 100 1, 10, 1001,10,100
  • 其次开始在l , r l, rl,r中枚举,如11 , 12 , . . . 19 11,12,…1911,12,…19
  • 当到了10的倍数时(比如20),意味着此位数字换了,也就是此位数字为x 的数枚举完了,return即可

有点不太好理解

import java.util.Scanner;

public class Main {

    static int n;
    static int sum = 0; // 枚举个数

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
        dfs(1, 9, 50);

    }

    // 在[left,right]中找k个数  k=50
    // 1<=left
    // left,right只相差一位数,如100,999
    public static void dfs(int left, int right, int k) {
        if (right > n) right = n; // 防止越界

        for (int i = left; i <= right; i++) { // 遍历[left,right]

            if (i != left && i % 10 == 0) // 比如left:10,right:99,i只需要遍历10-19就行了
                return; // 该位枚举完毕

            sum++;
            if (sum <= k) {
                System.out.println(i + ".mp4");
                if (sum == k) return;
            }

            if (i * 10 <= n)
                // 都增加一位
                dfs(i * 10, i * 100 - 1, k);

        }
    }
}

I:展览(线性基)

【参考:saikr oj | 展览】

考点:线性基
没看懂

K:礼物

【参考:saikr oj | 礼物】

签到题

import java.util.Arrays;
import java.util.Scanner;

public class Main {

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

        int[] arr=new int[n];

        for (int i = 0; i < n; i++) {
            arr[i]=sc.nextInt();
        }
        Arrays.sort(arr);

        System.out.println(arr[n-1]);
    }
}

L: 看错题 不会

线段树

你可能感兴趣的:(数据结构与算法,算法,java,leetcode)