蓝桥杯31天真题冲刺|题解报告|第十六天

文章介绍了作者snippet在蓝桥杯编程挑战中遇到的四道题目,涉及前缀和、单调队列和带权并查集等数据结构。第一题要求输出第n个大写字母,第二题是找出单词中出现频率最高的字母,第三题是火星旅行问题,需判断哪个空间站适合登陆,第四题是根据部分和信息推导区间和。文章提供了解题思路和Java代码实现。
摘要由CSDN通过智能技术生成

大家好,我是snippet,今天是刷蓝桥真题的第十六天,今天的题包含前缀和+单调队列(第三题)、带权并查集(第四题)的知识,第三题感觉是数据太多了导致的超时,今天的知识有点硬核,下面是我今天的题解 

目录

一、英文字母

问题描述

输入格式

输出格式

样例输入 1

样例输出 1

样例输入 2

样例输出 2

评测用例规模与约定

运行限制

二、单词分析

题目描述

输入描述

输出描述

输入输出样例

运行限制

三、火星旅行

题目描述

输入描述

输出描述

输入输出样例

运行限制

四、推导部分和

问题描述

输入格式

输出格式

样例输入

样例输出

评测用例规模与约定

运行限制


一、英文字母

题目链接:英文字母 - 蓝桥云课 (lanqiao.cn)

题目内容:

问题描述

输入一个正整数 n, 输出第 n 个大写英文字母。

输入格式

输入一行包含一个正整数 n 。

输出格式

输出一行包含一个字母。

样例输入 1

12

样例输出 1

L

样例输入 2

17

样例输出 2

Q

评测用例规模与约定

对于所有评测用例, 1≤n≤26 。

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

解题思路:

先输入数据n,把数据n+'A'-1,然后用字符类型输出数据

代码:

package 蓝桥杯31天真题冲刺.Day16;

import java.util.Scanner;

/**
 * @author snippet
 * @data 2023-03-19
 * 英文字母-蓝桥云课
 */
public class T1_英文字母 {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        System.out.println((char)(n-1+'A'));
    }
}

二、单词分析

题目链接:单词分析 - 蓝桥云课 (lanqiao.cn)

题目内容:

题目描述

小蓝正在学习一门神奇的语言,这门语言中的单词都是由小写英文字母组 成,有些单词很长,远远超过正常英文单词的长度。小蓝学了很长时间也记不住一些单词,他准备不再完全记忆这些单词,而是根据单词中哪个字母出现得最多来分辨单词。

现在,请你帮助小蓝,给了一个单词后,帮助他找到出现最多的字母和这 个字母出现的次数。

输入描述

输入一行包含一个单词,单词只由小写英文字母组成。

对于所有的评测用例,输入的单词长度不超过 1000。

输出描述

输出两行,第一行包含一个英文字母,表示单词中出现得最多的字母是哪个。如果有多个字母出现的次数相等,输出字典序最小的那个。

第二行包含一个整数,表示出现得最多的那个字母在单词中出现的次数。

输入输出样例

示例 1

输入

lanqiao

输出

a

2

示例 2

输入

longlonglongistoolong

输出

o

6

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

解题思路:

用一个一维数组来存每个字符出现的次数,再用一个max来存出现次数最多的字符出现的次数,按字典序输出第一个出现次数为max的子符同时输出max的值

代码:

package 蓝桥杯31天真题冲刺.Day16;

import java.util.Scanner;

/**
 * @author snippet
 * @data 2023-03-19
 * 单词分析-蓝桥云课
 */
public class T2_单词分析 {
    static int[] arr = new int[26];
    static int max;

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String s = sc.nextLine();
        for (int i = 0; i < s.length(); i++) {
            int t = ++arr[s.charAt(i)-'a'];
            max = Math.max(max, t);
        }
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == max) {
                System.out.println((char)(i+'a'));
                System.out.println(max);
                return;
            }
        }
    }
}

三、火星旅行

题目链接:火星旅行 - 蓝桥云课 (lanqiao.cn)

题目内容:

题目描述

火星的所有空间站都位于一个圆上,Byteazar 在其中一个空间站登陆然后开始绕圈旅行。

旅行需要耗费油料,一升油料只能跑 1 米,每个空间站可以补给的油料都有所不同。

Byteazar 每到一个空间站便可以把该空间站的油料全部拿走(他的油箱是没有容量限制的)。但是如果走到某个时候突然没油了那么旅行便失败了。

Byteazar 需要决定要在哪个地方登陆使得他能顺利访问完所有的空间站后回到他当初登陆的地方,他登陆后可以选择两个方向中的任意一个进行旅行。

输入描述

第一行一个整数 n,代表空间站数量,所有空间站由 1 至 n 进行标号。

之后 n 行,每行两个整数 pi​,di​,第 i+1 行描述了第 i 号空间站的信息,其中 pi​ 表示该空间站可以补给的油量,di​ 则指明了它到 i+1 号空间站的距离,对于 n 号空间站,di​ 表示它和 1 号空间站的距离。

其中,3≤n≤10^6,pi​≥0,di​>0,∑di​≤2×109。

输出描述

输出 n 行,每行一个字符串 TAK 或 NIE

若你认为在 i 号空间站登陆是可行的,则需要在第 i 行输出 TAK,否则输出 NIE

输入输出样例

示例 1

输入

5

3 1

1 2

5 2

0 1

5 4

输出

TAK
NIE
TAK
NIE
TAK

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

解题思路:

这个题可视为循环的空间站,只要每个空间站可以在够油的情况下通过一次就可以了,我们可以使用单调队列来对每个位置进行遍历并判断,在判断的时候 我们需要先求从第一个空间站到每个空间站的加油量-空间站的距离的值的和值,用来进行区间判断是否可以从k位置开始进(从k位置进,遍历每个位置,看补给油量是否大于距离)

在使用单调队列的时候我们可以使用数组滑窗或者双端队列来档滑窗都可以

可能是这个题的数据太多了,后面两个案例超时过不了

代码:

package 蓝桥杯31天真题冲刺.Day16;

import java.io.*;
import java.util.Deque;
import java.util.LinkedList;

/**
 * @author snippet
 * @data 2023-03-19
 * 推导部分和-蓝桥云课
 */
// 前缀和+单调队列
// 单调队列 可以使用数组滑窗 或者 双端队列滑窗都可以
// 但是这个题数据太多了 JavaAC不了 后面两个数据会超时
public class T3_火星旅行 {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    static int n;// n表示空间站的个数
    static int N = 1000100;
    static int[] s = new int[N * 2];
    static int[] p = new int[N];// 一维数组p存该空间站的加油量
    static int[] d = new int[N];// 一维数组d存该空间站到下一空间站的距离 如果是最后一个位置则是到1号空间站的距离
    static boolean[] ans = new boolean[N];// 一维数组ans存该位置是不是可以成为初始位置
    static int[] q = new int[N * 2];// 数组滑窗
//    static Deque<Integer> queue = new LinkedList<>();// 双端队列

    public static void main(String[] args) throws IOException {
        String[] str = br.readLine().split(" ");
        n = Integer.parseInt(str[0]);
        for (int i = 1; i <= n; i++) {
            str = br.readLine().split(" ");
            p[i] = Integer.parseInt(str[0]);
            d[i] = Integer.parseInt(str[1]);
        }

        // s数组里面存该位置的油量与下一位置的距离的差值
        for (int i = 1; i <= n; i++) {
            s[i] = p[i] - d[i];
            s[i + n] = s[i];
        }
        // 前缀和求1-->i位置的油量-距离的值的总和
        for (int i = 1; i <= 2 * n; i++) {
            s[i] += s[i-1];
        }
        
        // 队头为最小值
        // hh 表示头 tt 表示尾
        int hh = 0, tt = -1;
        q[hh] = 2 * n + 1;
        for (int i = 2 * n; i >= 1; i--) {
            if (hh <= tt && q[hh] > i + n - 1) hh++;
            if (i < n) {
                if (s[q[hh]] - s[i-1] >= 0) ans[i] = true;
            }
            while (hh <= tt && s[q[tt]] >= s[i-1]) tt--;
            q[++tt] = i-1;
        }
//        queue.addLast(2 * n + 1);
//        for (int i = 2 * n; i >= 1; i--) {
//            if (queue.size() > 0 && queue.getFirst() > i + n - 1) queue.removeFirst();
//            if (i < n) {
//                if (s[queue.getFirst()] - s[i - 1] >= 0) ans[i] = true;
//            }
//            while (queue.size() > 0 && s[queue.getLast()] >= s[i - 1]) queue.removeLast();
//            queue.addLast(i - 1);
//        }

        d[0] = d[n];
        for (int i = 1; i <= n; i++) {
            s[i] = p[i] - d[i - 1];
            s[i + n] = s[i];
        }
        for (int i = 1; i <= 2 * n; i++) {
            s[i] += s[i - 1];
        }

        // 队头为最大值
        // hh 表示头 tt 表示尾
        hh = 0;
        tt = -1;
        q[hh] = 0;
        for (int i = 0; i <= 2 * n - 1; i++) {
            if (hh <= tt && q[hh] > i + n - 1) hh++;
            if (i + 1 > n) {
                if (s[i+1] - s[q[hh]] >= 0) ans[i - n + 1] = true;
            }
            while (hh <= tt && s[q[tt]] <= s[i+1]) tt--;
            q[++tt] = i+1;
        }
//        queue.clear();
//        queue.addLast(0);
//        for (int i = 0; i <= 2 * n - 1; i++) {
//            if (queue.size() > 0 && queue.getFirst() < i - n + 1) queue.removeFirst();
//            if (i + 1 > n) {
//                if (s[i + 1] - s[queue.getFirst()] >= 0) ans[i - n + 1] = true;
//            }
//            while (queue.size() > 0 && s[queue.getLast()] <= s[i + 1]) queue.removeLast();
//            queue.addLast(i + 1);
//        }

        for (int i = 1; i <= n; i++) {
            if (ans[i]) pw.println("TAK");
            else pw.println("NIE");
        }
        pw.flush();
        br.close();
    }
}

四、推导部分和

题目链接:推导部分和 - 蓝桥云课 (lanqiao.cn)

题目内容:

问题描述

对于一个长度为 N 的整数数列 A1​,A2​,⋯AN​, 小蓝想知道下标 l 到 r 的部 分和 ∑i=lr​=Al​+Al+1​+⋯+Ar​ 是多少?

然而, 小蓝并不知道数列中每个数的值是多少, 他只知道它的 M 个部分和 的值。其中第 i 个部分和是下标 li​ 到 ri​ 的部分和 ∑j=li​ri​​=Ali​​+Ali​+1​+⋯+Ari​​, 值是 Si​ 。

输入格式

第一行包含 3 个整数 N、M 和 Q 。分别代表数组长度、已知的部分和数量 和询问的部分和数量。

接下来 M 行, 每行包含 3 个整数 li​,ri​,Si​ 。

接下来 Q 行, 每行包含 2 个整数 l 和 r, 代表一个小蓝想知道的部分和。

输出格式

对于每个询问, 输出一行包含一个整数表示答案。如果答案无法确定, 输出 UNKNOWN。

样例输入

5 3 3
1 5 15
4 5 9
2 3 5
1 5
1 3
1 2

样例输出

15
6
UNKNOWN

评测用例规模与约定

对于 10% 的评测用例, 1≤N,M,Q≤10,−100≤Si​≤100 。

对于 20% 的评测用例, 1≤N,M,Q≤20,−1000≤Si​≤1000 。

对于 30% 的评测用例, 1≤N,M,Q≤50,−10000≤Si​≤10000 。

对于 40% 的评测用例, 1≤N,M,Q≤1000,−10^6≤Si​≤10^6 。

对于 60% 的评测用例, 1≤N,M,Q≤10000,−10^9≤Si​≤10^9 。

对于所有评测用例, 1≤N,M,Q≤10^5,−10^12≤Si​≤10^12,1≤li​≤ri​≤N, 1≤l≤r≤N 。数据保证没有矛盾。

运行限制

  • 最大运行时间:3s
  • 最大运行内存: 512M

解题思路:

给定部分区间值求某些区间的连通的值,这也就是维护连通分量,我们可以使用带权并查集来维护连通分量,我直接套的带权并查集的板子;

这个题可以参考执梗大佬的题解:第十三届蓝桥杯JavaA组、C++A组省赛 J 题——推导部分和 (AC)_执 梗的博客-CSDN博客

代码:

package 蓝桥杯31天真题冲刺.Day16;

import java.io.*;

/**
 * @author snippet
 * @data 2023-03-19
 * 推导部分和-蓝桥云课
 */
// 带权并查集
class UF {
    long[] f, d;
    public UF(int n) {
        f = new long[n];
        d = new long[n];
        for (int i = 1; i < n; ++i) {
            f[i] = i;
        }
    }

    int find(int x) {
        if (x == f[x]) return (int) f[x];
        //先记录祖宗
        int root = find((int) f[x]);
        //加上父亲的距离
        d[x] += d[(int) f[x]];
        //指向祖宗
        return (int) (f[x] = root);
    }

    boolean same(int x, int y) {
        return find(x) == find(y);
    }

    // 数据存入
    boolean merge(int u, int v, long w) {
        int x = find(u);
        int y = find(v);
        if (x == y) return false;
        f[x] = y;
        d[x] = w + d[v] - d[u];
        return true;
    }
}

public class T4_推导部分和 {
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    static int n,m,q;
    static int l,r;
    static long s;

    public static void main(String[] args) throws IOException {
        String[] str = br.readLine().split(" ");
        n = Integer.parseInt(str[0]);
        m = Integer.parseInt(str[1]);
        q = Integer.parseInt(str[2]);

        UF uf = new UF(n + 10);

        // 数据存储
        for (int i = 1; i <= m; i++) {
            str = br.readLine().split(" ");
            l = Integer.parseInt(str[0]);
            r = Integer.parseInt(str[1]);
            s = Long.parseLong(str[2]);
            // 在前缀和求区间[l,r]的和值时,我们一般使用s[r]-s[l-1]
            uf.merge(l-1, r, s);
        }

        for (int i = 1; i <= q; i++) {
            str = br.readLine().split(" ");
            l = Integer.parseInt(str[0]);
            r = Integer.parseInt(str[1]);
            if (!uf.same(l-1, r)) pw.println("UNKNOWN");
            else pw.println(uf.d[l - 1] - uf.d[r]);
        }
        pw.flush();
        br.close();
    }
}

蓝桥杯一个国内著名的计算机比赛,为了帮助参赛者更好地准备和了解比赛的型,组委会会公布历年的真并提供相应的题解。 首先,我们需要了解蓝桥杯一个综合性的计算机比赛,测试的对象包括计算机基础知识、编程能力以及解决实际问的能力。 在历年的真中,参赛者将面临不同类型的目,包括算法设计与优化问、数据结构与算法、编程等。其中针对Python B组的目主要考察的是对Python语言的掌握和应用能力。 目解答一般会包含以下几个方面的内容: 1. 目分析与理解:读取目,理解目的要求和限制条件。通过仔细分析目,确定目的输入与输出,以及问的核心。 2. 设计解决方案:根据目要求和限制条件,设计一个合适的解决方案。可以使用合适的算法和数据结构来解决问,并做出相应的性能优化。 3. 编写代码实现:根据设计的方案编写相应的代码实现。需要注意的是,Python语言有其独特的语法和特性,掌握好这些特性可以更好地完成编程任务。 4. 调试与测试:编写完代码后,需要进行调试和测试。通过运行样例输入和输出,检查代码是否符合目要求,并且没有逻辑上的错误。 5. 总结与优化:在完成目解答后,可以进行总结和优化。包括分析算法复杂度、代码风格和可读性等方面,以便在比赛中更好地表现。 在准备蓝桥杯时,可以通过阅读历年的真题解来了解比赛的难度和类型,针对性地进行练习和提高。同时也可以参加相关的培训班和讨论活动,与其他参赛者交流经验和技巧。 总而言之,历年蓝桥杯的解答对于提高自己的编程能力和应对比赛非常有帮助。通过认真分析和实践,可以更好地理解并掌握Python编程,并在比赛中取得更好的成绩。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值