河南农业大学2023春蓝桥杯赛前训练第五场

A [NOIP2018]标题统计

签到、遍历

遍历判断即可
下面代码写繁琐了,其实只需要判断不是 空格和换行就可以

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

public class Main {
    private static int N = (int) 1e6 + 10, n, m;
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        char[] s = sc.nextLine().toCharArray();
        
        long ans = 0;
        for (int i = 0; i < s.length; i++) {
            if (('a' <= s[i] && s[i] <= 'z') || ('0' <= s[i] && s[i] <= '9') || ('A' <= s[i] && s[i] <= 'Z'))
                ans++;
        }
        
        System.out.println(ans);
    }
}

简化

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

public class Main {
    private static int N = (int) 1e6 + 10, n, m;
    
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        char[] s = sc.nextLine().toCharArray();
        
        long ans = 0;
        for (int i = 0; i < s.length; i++) {
            if (s[i] != ' ' && s[i] != '\n')
                ans++;
        }
        
        System.out.println(ans);
    }
}

B [NOIP2018]***

模拟

模拟,但是要注意 int溢出
注意一点:中立兵营也可以放兵,所以最后遍历的时候直接遍历整个数组判断即可

/**
 * @author :Changersh
 * @date : 2023/1/14 15:44
 */

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

public class Main {
    private static int N = (int) 1e6 + 10, n, m, p, s1, s2;
    private static long ans = 0, mn = 0, l = 0, r = 0;
    private static long[] a = new long[N];

    public static void main(String[] args) {
        n = sc.nextInt();
        for (int i = 1; i <= n; i++) a[i] = sc.nextLong();
        m = sc.nextInt(); // 中立号
        p = sc.nextInt(); // 要增加的兵营号
        s1 = sc.nextInt(); // 数量
        s2 = sc.nextInt(); // 数量

        a[p] += s1;

        for (int i = 1; i < m; i++) l += a[i] * (m - i);
        for (int i = m + 1; i <= n; i++) r += a[i] * (i - m);

        mn = Long.MAX_VALUE;
        for (int i = 1; i <= n; i++) {
            long t = (long) s2 * (m - i);
            if (Math.abs(r - l - t) < mn) {
                mn = Math.abs(r - l - t);
                ans = i;
            }
        }
        pw.println(ans);

        pw.close();
    }
}

F [NOIP2012]借教室

二分 + 差分 + 前缀和

先对教室数组求差分,然后二分订单号,找到最小的不满足的订单号。
用 c 做差分的临时数组

/**
 * @author :Changersh
 * @date : 2023/3/26 15:44
 * 二分答案
 */

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

public class Main {
    private static int N = (int) 1e6 + 10, n, m, ans = 0, idx = 0;
    private static int[] a = new int[N], c = new int[N];
    private static int[][] b = new int[N][3];

    public static void main(String[] args) {
        n = sc.nextInt();
        m = sc.nextInt();
        for (int i = 1; i <= n; i++) a[i] = sc.nextInt();
        for (int i = 1; i <= m; i++) {
            b[i][0] = sc.nextInt();
            b[i][1] = sc.nextInt();
            b[i][2] = sc.nextInt();
        }

        for (int i = n; i >= 1; i--) a[i] -= a[i - 1];

        int l = 1, r = m + 1;
        while (l < r) {
            int mid = l + ((r - l) >> 1);
            if (check(mid)) r = mid;
            else l = mid + 1;
        }

        if (check(r)) pw.println(-1 + "\n" + r);
        else pw.println("0");

        pw.close();
    }

    // 差分 + 前缀和 判断是否合格???
    private static boolean check(int x) {
        for (int i = 1; i <= n; i++) c[i] = a[i]; // 复制数组

        for (int i = 1; i <= x; i++) {
            c[b[i][1]] -= b[i][0];
            c[b[i][2] + 1] += b[i][0];
        }
        long sum = 0;
        for (int i = 1; i <= n; i++) {
            sum += c[i];
            if (sum < 0) return true;
        }

        return false;
    }
}

G [NOIP2010]机器翻译

队列 + 哈希表

原来用的数组模拟队列,结果一直有一个点过不去,现在也没看出来哪里错误了,模拟的队列应该错了,换成了 acwing 的模拟队列,过了
换成队列之后,过了

/**
 * @author :Changersh
 * @date : 2023/1/14 15:44
 */

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

public class Main {
    private static int N = 1010, n, m, ans = 0, idx = 0, x;
    private static boolean[] vis = new boolean[N];
    private static ArrayDeque<Integer> ad = new ArrayDeque<>();

    public static void main(String[] args) {
        m = sc.nextInt();
        n = sc.nextInt();

        for (int i = 0; i < n; i++) {
            x = sc.nextInt();
            if (vis[x]) continue;
            ad.addLast(x);
            vis[x] = true;
            ans++;
            
            while (ad.size() > m) {
                int t = ad.pollFirst();
                vis[t] = false;
            }
        }

        pw.println(ans);

        pw.close();
    }
}

模拟队列 + 哈希表

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


public class Main {
    private static int N = 1010, n, m, ans = 0, idx = 0, x, hh = 0, tt = -1;
    private static boolean[] vis = new boolean[N];
    private static int[] t = new int[N]; // 模拟队列
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        m = sc.nextInt();
        n = sc.nextInt();
        
        for (int i = 0; i < n; i++) {
            x = sc.nextInt();
            
            if (vis[x]) continue;
            ans++;
            t[++tt] = x;
            vis[x] = true;
            int p = (tt - hh + 1); // 要插入的位置
            if (p > m) vis[t[hh++]] = false;
        }
        
        
        System.out.println(ans);
    }   
}

H [CSP2020]优秀的拆分(power)

low_bit(x)

可以发现,当 x 是奇数时,就不是优秀的拆分,偶数都是优秀的拆分
拆分出来的是 不相同的 2 的次幂,也就是 x 二进制上的每一位,我们用 low_bit(x) 循环取数,放置在数组中,最后倒序输出即可

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

public class Main {
    private static int N = 1010, n, m, ans = 0, idx = 0;
    private static int[] a = new int[N];
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();
    
        if ((n & 1) == 1) System.out.println("-1");
        else {
            while (n > 0) {
                int t = low_bit(n);
                n -= t;
                a[idx++] = t;
            }
            
            for (int i = idx - 1; i >= 0; i--) System.out.print(a[i] + " ");
        }
    }
    
    private static int low_bit(int x) {
        return x & -x;
    }
}

I [CSP2020]直播获奖(live)

实时评测?桶排

题意是先给出获奖概率,然后按次序给出分数,人数每次加一,最少得有一个人获奖。
每次多一个人之后,就给出当前的分数线(即可以获奖的最低分数)
因为分数总共就 600 分,我们可以倒序遍历,查找获奖的分数线,当前人数总和 >= 获奖人数时,这个分数就是分数线

/**
 * @author :Changersh
 * @date : 2023/3/26 15:44
 */

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

public class Main {
    private static int N = (int) 1e5 + 10, n, w, x, y, sum, t;
    private static int[] a = new int[610]; // 记录每个数的数量

    public static void main(String[] args) {
        n = sc.nextInt();
        w = sc.nextInt(); // 输入的是个整数,需要 / 100 才是小数概率

        for (int i = 1; i <= n; i++) {
            x = i * w / 100; // 获奖人数
            sum = 0;

            if (x < 1) x = 1; // 获奖人数不能小于 1
            t = sc.nextInt(); // 读入选手的分数
            a[t]++;            // 分数标记 + 1

            for (int j = 600; j >= 0; j--) {
                sum += a[j];
                if (sum >= x) {
                    pw.print(j + " "); // 输出获奖分数线,所以只需要输出最小的分数即可
                    break;
                }
            }
        }

        pw.close();
    }
}

J [NOIP2017]棋盘

dfs

注意细节,左上角一定是有颜色的

/**
 * @author :Changersh
 * @date : 2023/3/26 15:44
 */

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

public class Main {
    private static final int inf = Integer.MAX_VALUE;
    private static int N = 1010, n, m, ans = Integer.MAX_VALUE;
    private static int[][] g = new int[N][N]; // 颜色
    private static int[] dx = {-1, 0, 1, 0}, dy = {0, 1, 0, -1};
    private static int[][] dis = new int[N][N];

    public static void main(String[] args) {
        n = sc.nextInt();
        m = sc.nextInt();

        for (int i = 0; i < N; i++) Arrays.fill(dis[i], 0x3f3f3f3f);
        int x, y, c;
        while (m-- > 0) {
            x = sc.nextInt();
            y = sc.nextInt();
            c = sc.nextInt();
            g[x][y] = c + 1; // 1 红色,2 黄色,0 无色
        }

        dfs(1, 1, 0, false); // 从(1, 1) 开始,目前总金币是 0,没有使用变色

        if (ans == inf) pw.println(-1);
        else pw.println(ans);

        pw.close();
    }

    private static void dfs(int x, int y, int sum, boolean magic) {
        if (x <= 0 || x > n || y <= 0 || y > n) return; // 越界
        if (g[x][y] == 0) return;
        if (sum >= dis[x][y]) return; // 没必要了

        dis[x][y] = sum;
        if (x == n && y == n) {
            if (sum < ans) ans = sum;
            return;
        }

        for (int i = 0; i < 4; i++) {
            int nx = x + dx[i];
            int ny = y + dy[i];

            if (nx <= 0 || nx > n || ny <= 0 || ny > n) continue;
            if (g[nx][ny] != 0) {
                if (g[x][y] == g[nx][ny]) dfs(nx, ny, sum, false);
                else dfs(nx, ny, sum + 1, false);
            } else if (g[nx][ny] == 0 && !magic) {
                g[nx][ny] = g[x][y];
                dfs(nx, ny, sum + 2, true);
                g[nx][ny] = 0;
            }
        }
    }
}

你可能感兴趣的:(蓝桥杯,java,算法)