2020年 第11届 蓝桥杯 Java B组 第1次模拟赛真题详解及小结(校内模拟)


  • 注意:部分代码及程序 源自 蓝桥杯 官网视频(历年真题解析) 郑未老师
  1. 2013年 第04届 蓝桥杯 Java B组 省赛真题详解及小结
  2. 2014年 第05届 蓝桥杯 Java B组 省赛真题详解及小结
  3. 2015年 第06届 蓝桥杯 Java B组 省赛真题详解及小结
  4. 2016年 第07届 蓝桥杯 Java B组 省赛真题详解及小结
  5. 2017年 第08届 蓝桥杯 Java B组 省赛真题详解及小结
  6. 2018年 第09届 蓝桥杯 Java B组 省赛真题详解及小结
  7. 2019年 第10届 蓝桥杯 Java B组 省赛真题详解及小结
  8. 2020年 第11届 蓝桥杯 Java B组 第1次模拟赛真题详解及小结(校内模拟)
  9. 2020年 第11届 蓝桥杯 Java B组 第2次模拟赛真题详解及小结
  10. 2020年 第11届 蓝桥杯 C/C++ B组 省赛真题详解及小结【第1场省赛 2020.7.5】【Java版】
  11. 2020年 第11届 蓝桥杯 Java B组 省赛真题详解及小结【第1场省赛 2020.7.5】
  12. 2020年 第11届 蓝桥杯 Java C组 省赛真题详解及小结【第1场省赛 2020.7.5】

目   录

一、15.125GB

二、约数个数

三、叶结点数

四、数字9

A04_indexOf

五、数位递增的数

六、递增三元组

七、音节判断

方法一

方法二

八、长草

九、序列计数

A09_序列计数_1记忆型递归

A09_序列计数_2优化

十、晚会节目单

方法一

方法二

小结


 

一、15.125GB

【问题描述】

在计算机存储中,15.125GB是多少MB?

【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

【答案】:15488

【解析】:1G=1024M

二、约数个数

【问题描述】

1200000有多少个约数(只计算正约数)。

【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

【答案】:96

【解析】:枚举+检查

约数,又称因数。
整数a除以整数b(b≠0) 除得的商正好是整数而没有余数,我们就说a能被b整除,或b能整除a。
a称为b的倍数,b称为a的约数。

三、叶结点数

【问题描述】

一棵包含有2019个结点的二叉树,最多包含多少个叶结点?

【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

【答案】:1010

【解析】:思路   n=n0+n1+n2,为使叶子节点数(n0)最多,必须n1最小,设为0,而n0=n2+1

得n2=(2019-1)/2=1009

所以n0=1010

四、数字9

【问题描述】

在1至2019中,有多少个数的数位中包含数字9?

注意,有的数中的数位中包含多个9,这个数只算一次。例如,1999这个数包含数字9,在计算只是算一个数。

【答案提交】

这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

【答案】:544

思路
伪代码:
for i from 9  to 2019
    if str(i).contains('9')
        ans++

package simulationMatch_11_2020;

public class A04_数字9 {

	static final int N = 2019;

	static boolean check(int i) {
		String str = "" + i;
		return str.indexOf('9') != -1;
	}

	public static void main(String[] args) {
		int ans = 0;
		for (int i = 9; i <= N; ++i) {
			if (check(i)) {
				ans++;
			}
		}
		System.out.println(ans);
	}

}

A04_indexOf

public int indexOf(int ch): 
    返回指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。

public int indexOf(int ch, int fromIndex): 
    返回从 fromIndex 位置开始查找指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。

int indexOf(String str): 
    返回指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。

int indexOf(String str, int fromIndex): 
    返回从 fromIndex 位置开始查找指定字符在字符串中第一次出现处的索引,如果此字符串中没有这样的字符,则返回 -1。 

package simulationMatch_11_2020;

public class A04_indexOf {

	public static void main(String[] args) {
		String str = "aaa456ac";
		// 查找指定字符是在字符串中的下标。在则返回所在字符串下标;不在则返回-1.
		System.out.println(str.indexOf("b")); // indexOf(String str); 返回结果:-1,"b"不存在

		// 从第四个字符位置开始往后继续查找,包含当前位置
		System.out.println(str.indexOf("a", 3));// indexOf(String str, int fromIndex); 返回结果:6

		// (与之前的差别:上面的参数是 String 类型,下面的参数是 int 类型)参考数据:a-97,b-98,c-99

		// 从头开始查找是否存在指定的字符
		System.out.println(str.indexOf(99));// indexOf(int ch);返回结果:7
		System.out.println(str.indexOf('c'));// indexOf(int ch);返回结果:7

		// 从fromIndex查找ch,这个是字符型变量,不是字符串。字符a对应的数字就是97。
		System.out.println(str.indexOf(97, 3));// indexOf(int ch, int fromIndex); 返回结果:6
		System.out.println(str.indexOf('a', 3));// indexOf(int ch, int fromIndex); 返回结果:6
		
		
		
		String Str = new String("菜鸟教程:www.runoob.com");
		String SubStr1 = new String("runoob");
		String SubStr2 = new String("com");

		System.out.print("查找字符 o 第一次出现的位置 :");
		System.out.println(Str.indexOf('o'));

		System.out.print("从第14个位置查找字符 o 第一次出现的位置 :");
		System.out.println(Str.indexOf('o', 14));

		System.out.print("子字符串 SubStr1 第一次出现的位置:");
		System.out.println(Str.indexOf(SubStr1));

		System.out.print("从第十五个位置开始搜索子字符串 SubStr1 第一次出现的位置 :");
		System.out.println(Str.indexOf(SubStr1, 15));

		System.out.print("子字符串 SubStr2 第一次出现的位置 :");
		System.out.println(Str.indexOf(SubStr2));
	}

}

五、数位递增的数

【问题描述】

一个正整数如果任何一个数位不大于右边相邻的数位,则称为一个数位递增的数,例如1135是一个数位递增的数,而1024不是一个数位递增的数。

给定正整数 n,请问在整数 1 至 n 中有多少个数位递增的数?

【输入格式】

输入的第一行包含一个整数 n。

【输出格式】

输出一行包含一个整数,表示答案。

【样例输入】

30

【样例输出】

26

【评测用例规模与约定】

对于 40% 的评测用例,1 <= n <= 1000。
对于 80% 的评测用例,1 <= n <= 100000。
对于所有评测用例,1 <= n <= 1000000。

【解析】:

思路 O(kN)
迭代1~n
    转换为字符串
    迭代字符串的每一位,判断是否满足要求

package simulationMatch_11_2020;

import java.util.Scanner;

public class A05_数位递增的数 {

	static Scanner sc = new Scanner(System.in);

	public static void main(String[] args) {
		while (true) // 死循环为测试用
			work();
	}

	static void work() {
		int n = sc.nextInt();
		int ans = 0;
		for (int i = 1; i <= n; ++i) {
			String s = "" + i;
			boolean flag = true;
			for (int j = 1; j < s.length(); ++j) {
				if (s.charAt(j - 1) > s.charAt(j)) {
					flag = false;
					break;
				}
			}
			if (flag)
				ans++;
		}
		System.out.println(ans);
	}

}

六、递增三元组

【问题描述】
在数列 a[1], a[2], …, a[n] 中,如果对于下标 i, j, k 满足 0<i<j<k<n+1 且 a[i]<a[j]<a[k],则称 a[i], a[j], a[k] 为一组递增三元组,a[j]为递增三元组的中心。
给定一个数列,请问数列中有多少个元素可能是递增三元组的中心。
【输入格式】
输入的第一行包含一个整数 n。
第二行包含 n 个整数 a[1], a[2], …, a[n],相邻的整数间用空格分隔,表示给定的数列。
【输出格式】
输出一行包含一个整数,表示答案。
【样例输入】
5
1 2 5 3 5
【样例输出】
2
【样例说明】
a[2] 和 a[4] 可能是三元组的中心。
【评测用例规模与约定】
对于 50% 的评测用例,2 <= n <= 100,0 <= 数列中的数 <= 1000。
对于所有评测用例,2 <= n <= 1000,0 <= 数列中的数 <= 10000。

【解析】:

思路 O(N^2)
枚举每个元素
    该元素与前面的元素比较,找到小的即可
    该元素与后面的元素比较,找到大的即可
    上面两项为真,即说明当前元素可以作为三元组的中心

O(N^2),因为N最大为1000,所以1秒内可以解决战斗。

package simulationMatch_11_2020;

import java.util.Scanner;

public class A06_递增三元组 {
	static Scanner sc = new Scanner(System.in);

	public static void main(String[] args) {
		while (true)// 死循环为测试用
			work();
	}

	static void work() {
		int n, ans = 0;
		n = sc.nextInt();
		int[] data = new int[n];
		for (int i = 0; i < n; ++i) {
			data[i] = sc.nextInt();
		}
		for (int j = 1; j < n - 1; ++j) {
			int hasSmall = 0;
			for (int i = 0; i < j; ++i) {
				if (data[i] < data[j]) {
					hasSmall = 1;
					break;
				}
			}
			int hasBig = 0;
			for (int k = j + 1; k < n; ++k) {
				if (data[j] < data[k]) {
					hasBig = 1;
					break;
				}
			}
			if ((hasSmall & hasBig) == 1)
				ans++;
		}
		System.out.println(ans);
	}
}

七、音节判断

【问题描述】
小明对类似于 hello 这种单词非常感兴趣,这种单词可以正好分为四段,第一段由一个或多个辅音字母组成,第二段由一个或多个元音字母组成,第三段由一个或多个辅音字母组成,第四段由一个或多个元音字母组成。
给定一个单词,请判断这个单词是否也是这种单词,如果是请输出yes,否则请输出no。
元音字母包括 a, e, i, o, u,共五个,其他均为辅音字母。
【输入格式】
输入一行,包含一个单词,单词中只包含小写英文字母。
【输出格式】
输出答案,或者为yes,或者为no。
【样例输入】
lanqiao
【样例输出】
yes
【样例输入】
world
【样例输出】
no
【评测用例规模与约定】
对于所有评测用例,单词中的字母个数不超过100。

【解析】:

思路1
正则表达式

思路2
将单词的辅音标记为0,元音标记为1,那么符合要求的单词形态为0+ 1+ 0+ 1
在限定开头必须为0,最后必须为1的情况下,01交替为3次,即前后元素相加结果为1的次数必须为3

方法一

package simulationMatch_11_2020;

import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class A07_音节判断 {
	// 编译一个pattern模式
	static Pattern p = Pattern.compile("[^aeiou]+[aeiou]+[^aeiou]+[aeiou]+");
	static Scanner sc = new Scanner(System.in);

	public static void main(String[] args) {
		while (true) { // 死循环是为了测试
			if (work())
				System.out.println("yes");
			else
				System.out.println("no");
		}
	}

	static boolean work() {
		String word = sc.nextLine();
		Matcher m = p.matcher(word); //匹配器
		return m.matches();//判断是否匹配
	}

}

方法二

package simulationMatch_11_2020;

import java.util.Scanner;

public class A07_音节判断2 {
	static Scanner sc = new Scanner(System.in);

	public static void main(String[] args) {
		while (true) { // 死循环是为了测试
			if (work())
				System.out.println("yes");
			else
				System.out.println("no");
		}
	}

	static boolean isYuan(char c) {
		return c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u';
	}

	static boolean work() {
		String word = sc.nextLine();
		int size = word.length();
		if (size < 4)
			return false;
		if (isYuan(word.charAt(0)) || !isYuan(word.charAt(size - 1)))
			return false;
		int[] h = new int[size];
		for (int i = 0; i < size; ++i) {
			if (isYuan(word.charAt(i)))
				h[i] = 1;
			else
				h[i] = 0;
		}
		int cnt = 0;
		for (int i = 1; i < size; ++i) {
			if (h[i - 1] + h[i] == 1)
				cnt++;
		}
		return cnt == 3;
	}

}

八、长草

【问题描述】
小明有一块空地,他将这块空地划分为 n 行 m 列的小块,每行和每列的长度都为 1。
小明选了其中的一些小块空地,种上了草,其他小块仍然保持是空地。
这些草长得很快,每个月,草都会向外长出一些,如果一个小块种了草,则它将向自己的上、下、左、右四小块空地扩展,这四小块空地都将变为有草的小块。
请告诉小明,k 个月后空地上哪些地方有草。
【输入格式】
输入的第一行包含两个整数 n, m。
接下来 n 行,每行包含 m 个字母,表示初始的空地状态,字母之间没有空格。如果为小数点,表示为空地,如果字母为 g,表示种了草。
接下来包含一个整数 k。
【输出格式】
输出 n 行,每行包含 m 个字母,表示 k 个月后空地的状态。如果为小数点,表示为空地,如果字母为 g,表示长了草。
【样例输入】
4 5
.g...
.....
..g..
.....
2
【样例输出】
gggg.
gggg.
ggggg
.ggg.
【评测用例规模与约定】
对于 30% 的评测用例,2 <= n, m <= 20。
对于 70% 的评测用例,2 <= n, m <= 100。
对于所有评测用例,2 <= n, m <= 1000,1 <= k <= 1000。

【解析】:

思路 O(N*M)
典型的bfs,基本是个模板题。时间复杂度最多为O(N*M)。

加队列:1、未被访问;2、month < k

在Java中,用System.err.println();多次输出字符有问题。
// 缓冲字符输出流   积累
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
writer.flush();

package simulationMatch_11_2020;

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

public class A08_长草 {
	static final int[] dx = { 1, 0, -1, 0 };
	static final int[] dy = { 0, 1, 0, -1 };
	static Scanner sc;
	static int[][] vis = new int[1000][1000];
	static int N, M, K;

	public static void main(String[] args) throws IOException {
		long now = System.currentTimeMillis();
		// System.setIn(new FileInputStream(new File("***.in")));
		// System.setOut(new PrintStream(new File("***.out")));
		sc = new Scanner(System.in);
		N = sc.nextInt();
		M = sc.nextInt();
		sc.nextLine();
		LinkedList<Block> q = new LinkedList<Block>();
		for (int i = 0; i < N; i++) {
			String line = sc.nextLine();
			for (int j = 0; j < M; j++) {
				if (line.charAt(j) == 'g') {
					q.addLast(new Block(i, j, 0));// 加入队列
					vis[i][j] = 1; // 标记
				}
			}
		}
		K = sc.nextInt();

		while (!q.isEmpty()) {
			Block b = q.removeFirst();
			int month = b.month;
			if (month < K) {
				for (int i = 0; i <= 3; i++) {
					int nx = b.i + dx[i];
					int ny = b.j + dy[i];
					if (0 <= nx && nx < N && 0 <= ny && ny < M && vis[nx][ny] == 0) {
						vis[nx][ny] = 1;
						q.addLast(new Block(nx, ny, month + 1));
					}
				}
			}
		}
		// 缓冲字符输出流 积累
		BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(System.out));
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < M; j++) {
				if (vis[i][j] == 1)
					writer.write('g');
				else
					writer.write('.');
			}
			writer.write('\n');
		}
		writer.flush();
		System.err.println(System.currentTimeMillis() - now);
	}

	// 草地上的一块
	private static class Block {
		int i;
		int j;
		int month;

		public Block(int i, int j, int month) {
			this.i = i;
			this.j = j;
			this.month = month;
		}
	}

}

九、序列计数

【问题描述】
小明想知道,满足以下条件的正整数序列的数量:
1. 第一项为 n;
2. 第二项不超过 n;
3. 从第三项开始,每一项小于前两项的差的绝对值。
请计算,对于给定的 n,有多少种满足条件的序列。
【输入格式】
输入一行包含一个整数 n。
【输出格式】
输出一个整数,表示答案。答案可能很大,请输出答案除以10000的余数。
【样例输入】
4
【样例输出】
7
【样例说明】
以下是满足条件的序列:
4 1
4 1 1
4 1 2
4 2
4 2 1
4 3
4 4
【评测用例规模与约定】
对于 20% 的评测用例,1 <= n <= 5;
对于 50% 的评测用例,1 <= n <= 10;
对于 80% 的评测用例,1 <= n <= 100;
对于所有评测用例,1 <= n <= 1000。

【解析】:

历次类推:递归

思路:记忆型递归 O(N^3)
题干第三点,是一个递归定义,可以得到递归式:
    f(pre,cur) = f(cur,1) + f(cur,2) + ... +f(cur,abs(pre-cur)-1) + 1
    pre表示前一个数,cur代表当前的数,选定之后,序列种数等于以cur为前序,以1到abs-1为当前的序列数的总和再加1.
    如f(5,2) = f(2,1)+f(2,2).

但是暴力递归的复杂度是指数级;

基本的优化方案是加状态记忆:输入1000时,实测运行时间为1000~2000ms;

数据规模:50000 50000


进一步优化
至此,能通过80%的数据(在1000ms限制下);

解空间是N的平方(详细为N*N)表格,但是每次都要循环加总,所以成了N的立方,
在同样的解空间下,避免循环加总,即可优化到N的平方

重新考虑状态的转移:

如果我们用f(i,j)表示前一个数是i,当前数是1到j的合法序列的个数;
有f(i,j) = 1 + f(i,j-1) + f(j,abs(i-j)-1)即分为两个部分1)i作为前一个数,
从1到j-1为当前数的合法序列的个数已经计算好,2)求以j为尾数,
后面选择1到abs(i-j)-1的合法序列的个数。

如 f(10,5)=f(10,4)+f(5,4);而不是枚举1到5;这样每次解答树只展开两个节点,
相当于减少一层循环,虽然解答树的层次还是很深,但是由于记忆的存在,
解空间仍然是N的平方。可在100ms内解决。

A09_序列计数_1记忆型递归

package simulationMatch_11_2020;

import java.util.Scanner;

public class A09_序列计数_1记忆型递归 { // 参考代码:记忆型递归
	static final int MOD = 10000;
	static int N;
	static long ans;
	static long[][] mem = new long[1001][1000]; // 标记
	static Scanner sc;

	static long dfs(int pre, int cur) {
		// 询问状态
		if (mem[pre][cur] != 0)
			return mem[pre][cur]; // 前续 后继
		long ans = 1;
		for (int j = 1; j < Math.abs(pre - cur); j++) {
			ans = (ans + dfs(cur, j)) % MOD;
		}
		mem[pre][cur] = ans;
		return ans;
	}

	static void work() {
		ans = 0;
		N = sc.nextInt();
		long ago = System.currentTimeMillis();
		// f(pre,cur) = sum(f(cur,_new))|_new from 1 to abs(pre-cur)-1
		for (int x = 1; x <= N; ++x)
			ans = (ans + dfs(N, x)) % MOD;
		System.out.println(ans);
		System.err.println(System.currentTimeMillis() - ago);
	}

	public static void main(String[] args) {
		sc = new Scanner(System.in);
		while (true) {
			work();
		}
	}
}

A09_序列计数_2优化

package simulationMatch_11_2020;

import java.util.Scanner;

public class A09_序列计数_2优化 {
	static final int MOD = 10000;
	static int N;
	static long ans;
	static long[][] mem = new long[1001][1000];
	static Scanner sc;

	static long dfs(int pre, int cur) {
		if (cur <= 0)
			return 0;
		// 询问状态
		if (mem[pre][cur] != 0)
			return mem[pre][cur];
		mem[pre][cur] = (1 + dfs(pre, cur - 1) + dfs(cur, Math.abs(pre - cur) - 1)) % MOD;
		return mem[pre][cur];
	}

	static void work() {
		ans = 0;
		N = sc.nextInt();
		long ago = System.currentTimeMillis();
		System.out.println(dfs(N, N));
		System.err.println(System.currentTimeMillis() - ago);
	}

	public static void main(String[] args) {
		sc = new Scanner(System.in);
		while (true) {
			work();
		}
	}
}

十、晚会节目单

【问题描述】
小明要组织一台晚会,总共准备了 n 个节目。然后晚会的时间有限,他只能最终选择其中的 m 个节目。
这 n 个节目是按照小明设想的顺序给定的,顺序不能改变。
小明发现,观众对于晚会的喜欢程度与前几个节目的好看程度有非常大的关系,他希望选出的第一个节目尽可能好看,在此前提下希望第二个节目尽可能好看,依次类推。
小明给每个节目定义了一个好看值,请你帮助小明选择出 m 个节目,满足他的要求。
【输入格式】
输入的第一行包含两个整数 n, m ,表示节目的数量和要选择的数量。
第二行包含 n 个整数,依次为每个节目的好看值。
【输出格式】
输出一行包含 m 个整数,为选出的节目的好看值。
【样例输入】
5 3
3 1 2 5 4
【样例输出】
3 5 4
【样例说明】
选择了第1, 4, 5个节目。
【评测用例规模与约定】
对于 30% 的评测用例,1 <= n <= 20;
对于 60% 的评测用例,1 <= n <= 100;
对于所有评测用例,1 <= n <= 100000,0 <= 节目的好看值 <= 100000。

【解析】:

错误思路
如果用两次排序求解,那就错了。因为并不是要选出的方案的好看值总和最大,而是要从前往后尽量好看。即选出的M个数字典序最大

思路 O(N^2)
此题关键在于“第一个节目尽可能好看”并希望“第二个节目尽可能好看”……那么我们选择的第一节目就是max(g[0]~g[n-m])闭区间,要选择的第二个节目是max(g[lastMax+1],g[n-m+1])及从上一个节目往下到n-m+1这个区间里面选最好看的,直到剩下的必须全部选择。

算法用尺取法,双指针移动。理论上的复杂度是O(M*(N-M)),极端情况是M=N/2,整体达到(N^2)/2。如果输入数据为:

100000 50000
100000 99999 ...
1
2
实测运行时间为:10秒以上

优化:区间最值查询 O(NlogN)
while (pos_1 < pos_2)
    if (games[++pos_1] > games[pos_max])pos_max = pos_1;

这一段代码是区间内查询最大值,反复多次,且数据是静态的,所以选择ST做RMQ。

f[i][j]表示以 i 为起点,连续 2^j 个数中的最大值(的下标);

转移方程就是:f[i][j] = data[f[i][j-1]] >= data[f[i+pow_2(j-1)][j-1]]?f[i][j-1]:f[i+pow_2(j-1)][j-1]; 注:比较原始数据,记录下标

由于预处理是O(nlogn),M次查询是O(M),每次查询是O(1),所以整体复杂度为O(nlogn)。

下列代码实测运行时间100ms以内

方法一

package simulationMatch_11_2020;

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

public class A10_晚会节目单 {
	public static Scanner sc;
	public static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
	static int N, M;
	private static int[] data;

	/* ===st rmq begin=== */
	private static int[][] st;
	private static int[] Log;

	private static int pow_2(int x) {
		return 1 << x;
	}

	private static void initLog() {
		Log = new int[N + 1];
		Log[1] = 0;
		for (int i = 2; i <= N; i++) {
			Log[i] = Log[i / 2] + 1;
		}
	}

	private static void initSt() {
		st = new int[N][Log[N] + 1];
		for (int i = 0; i < N; i++) {
			st[i][0] = i;// 注意此处记录索引
		}
		for (int j = 1; pow_2(j) < N; j++) {
			for (int i = 0; i + pow_2(j - 1) < N; i++) {
				int index1 = st[i][j - 1];
				int index2 = st[i + pow_2(j - 1)][j - 1];
				st[i][j] = data[index1] >= data[index2] ? index1 : index2;
			}
		}
	}

	private static int query(int l, int r) {
		int len = r - l + 1;
		int k = Log[len];

		int index1 = st[l][k];
		int index2 = st[r - pow_2(k) + 1][k];

		return data[index1] >= data[index2] ? index1 : index2;
	}
	/* ===st rmq end=== */

	public static void main(String[] args) throws IOException {
		long ago = System.currentTimeMillis();
		System.setIn(new FileInputStream(new File("E:\\data\\my10_1.in")));
		sc = new Scanner(System.in);
		N = sc.nextInt();
		M = sc.nextInt();
		data = new int[N];
		for (int i = 0; i < N; i++) {
			data[i] = sc.nextInt();
		}
//        初始化st数据
		initLog();
		initSt();
		int pos_max = 0, pos_1 = 0, pos_2 = N - M;
		while (pos_1 < pos_2 && pos_2 < N) {
//            while (pos_1 < pos_2)
//                if (data[++pos_1] > data[pos_max]) pos_max = pos_1;
			pos_max = query(pos_1, pos_2);
			bw.write(data[pos_max] + " ");
			pos_1 = pos_max + 1;
			pos_2++;
//            pos_max = pos_1;
		}
		while (pos_2 != N) {
			bw.write(data[pos_2++] + " ");
		}
		bw.write('\n');
		bw.flush();
		System.err.println(System.currentTimeMillis() - ago);
	}
}

方法二

package simulationMatch_11_2020;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Scanner;

public class A10_晚会节目单2_优化 {
	public static Scanner sc = new Scanner(System.in);
	public static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
	static int N, M;

	public static void main(String[] args) throws IOException {
		N = sc.nextInt();
		M = sc.nextInt();
		int[] games = new int[N];
		for (int i = 0; i < N; i++) {
			games[i] = sc.nextInt();
		}
		int pos_max = 0, pos_1 = 0, pos_2 = N - M;
		while (pos_1 < pos_2 && pos_2 < N) {
			while (pos_1 < pos_2)
				if (games[++pos_1] > games[pos_max])
					pos_max = pos_1;
			bw.write(games[pos_max] + " ");
			pos_1 = pos_max + 1;
			pos_2++;
			pos_max = pos_1;
		}
		while (pos_2 != N) {
			bw.write(games[pos_2++] + " ");
		}
		bw.write('\n');
		bw.flush();
	}
}

小结

暂无!

猜你喜欢

转载自blog.csdn.net/weixin_44949135/article/details/108179383