3.xx大学的模拟题
1.基础知识
- 顺序
- 选择
- 循环
- 数组宁符数组
- 结构体
- 函数
- 全排列
- multimap
1.*梦里的难题
生化危机血腥暴力的场面对小星星的冲击很大,晚上频繁地做起了梦,梦里他担负起拯救世人消灭僵尸的重任,眼看就能拿到消除 T 病毒的解药还世界清静,但 T 病毒人工智能电脑挡住了星星的去路,它声称研制出 T 病毒的目的是因为察觉人类智力退化,只有聪明的人才能存活下来,如果想要拿到解药,必须回答出下面这个难题:
有 N(1≤N≤100000)个数字(由 1 到 K 组成,1≤K≤10000),排成一列形成数字串,例如 1,5,3,2,5,1,3,4,4,2,5,1,2,3 它包含了很多的子序列,比如(5)、(1,3,2)、(1,5,3)、(3,4,1,3),请思考该列数字串不包含的最短的由 1 到 K 组成的的子序列长度是多少?
思路:
若有长度为1的子序列存在,则题中数的序列中必有k个数的一种全排列(可不连续)。同理,若有长度为2的子序列存在,则在第一个全排列后必再有一组k个数的全排列(可不连续),则只需要扫描n个数,能找到几组全排列(可不连续),即为答案。
2.幼儿园小朋友们的难题
https://blog.csdn.net/qq_45159762/article/details/104234100
输入
输入有多组数据。每组输入一个句子(一定包含数字字符,可能包含空格),长度小于256,占一行
输出
输出对应有多行,每行输出所找出的最大的那个非负整
样例输入:
&&12345aBsdDkjie64skjd5lk
3*2&&0%%%00B58CD000000b
a000b0000000c000
样例输出
12345
58
0
public class 幼儿园小朋友们的难题1016 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while(true) {
String ss = scanner.nextLine();
if (ss.equals("")) {
break;
}
char[] ssArray = ss.toCharArray();
//每行最大的数字
String max = "0";
//对数组里的每个字母进行判断
for (int i = 0; i < ssArray.length; i++) {
//判断这个字母是否是数字,数字不要以0为开头
if (ssArray[i]>'0' && ssArray[i] <='9' ) {
String b ="";
//判断这个字幕的下一个字母是否是数字,直到不是
//数字为止,这里的i的下标值很巧妙
while(ssArray[i]>='0' && ssArray[i] <='9') {
b +=ssArray[i++];
}
//现在b里是一连串数字
if (b.length()>max.length() ||
(b.length() == max.length() && (b.compareTo(max)>0))) {
//如果b里的数字大于max的值
max = b;
}
}
}
System.out.println(max);
}
}
}
3.池塘的水草1017
输入
输入有多行。第一行包含一个整数N(0 < N < 1000),表示有N组数据。
接下来N行,每行有一个整数m(1<m<109),表示m天长满池塘的水面。
输出
每组数据输出一个整数,代表水草第几天能长到池塘水面的一半。
样例输入
2
10
2
样例输出
9
1
import java.util.Scanner;
public class 池塘的水草1017 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
for (int i = 0; i < n; i++) {
int m = scanner.nextInt();
System.out.println(m-1);
}
}
}
4.1018: 青岛大虾
输入
输入包含多组数据。
每组包含两个数据,占一行。第一个数是一个浮点数area(30<=area<=800),表示每套住房的建筑面积,第二个数是一个整数N(100<= N <=1000),表示每套住房每平米的价格,即每平米卖多少只大虾,大虾的价格都是按市场价38元/只计算。
输出
对应每组输入数据,输出购买该住房需要实际花费的总价(单位:元)
样例输入
90.12 170
120 130
204.51 200
样例输出
582100
592800
1554200
import java.util.Scanner;
public class 青岛大虾1018 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String ss = scanner.nextLine();
while (!ss.equals("")) {
String[] ss1 = ss.split(" ");
float area = Float.valueOf(ss1[0]);
int price = Integer.valueOf(ss1[1])*38;
int sum = (int) (price*area);
int shengyu = sum%100;
//取零是重点
sum = sum- shengyu;
System.out.println(sum);
ss = scanner.nextLine();
}
}
}
2基本算法
- 枚举
- 模拟
- 递归
- 分治
- 排序
- 构造前缀和
- 差分
- 双向搜索
1.枚举
1. 1027: 你的QQ多少级了?
题目描述
QQ等级是2003年腾讯公司推出的QQ中的一种制度。最早是以小时来计算的,那段时间,绝大部分QQ用户都在挂QQ。随后就有不少媒体指责其浪费能源。在有关部门的介入下,腾讯公司将QQ等级变为以天为单位,每天只要在线两个小时就算一天。 半小时以上、两小时以下则记为半天。QQ等级最先开始的样子是星星,4个星星等于一个月亮,4个月亮等于一个太阳。4个太阳等于一个皇冠。(即:1个星星为1级,1个月亮为4级,1个太阳为16级,1个皇冠为64级。)一开始增加一个星星只用几天,到后面就要越来越多的天数来升级了。
用户可以在好友资料的浮出Tips显示中查看好友的在线等级,也可以在主面板自己头像的浮出Tips中查看自己的在线等级。用户到达每个等级需要的总天数可用如下的计算公式计算:
Days = Level * Level + Level * 4
现在你需要做的工作是根据给出的天数,计算用户的当前等级。
输入
输入仅一行,为一个非负整数Days,表示用户的活跃天数,输入数据在int表示的范围内。
输出
输出仅一行:一个整数表示用户的等级。
样例输入
867
样例输出
27
import java.util.Scanner;
public class QQ等级 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
long dags = scanner.nextLong();
int level = 1;
long sum = level*(level+4);
//注意边界值的判断
while (sum<=dags) {
level++;
sum = level*(level+4);
}
System.out.println(--level);
}
}
2.模拟
- 按照题目给的操作,用代码依次描述出来即可。
1.1024: 学霸猫
在我认识它的时候,它就已经叫学霸猫了,虽然我不知道它名字的由来,但在石大这种地方被冠以学霸之名。它经常会光顾正在上课的教室,并跟同学们一起耐心听讲,学校的教学楼、机房里到处都留下它的倩影,相信它将来会成为一个Doctor Cat。有心的同学记录下了它出现的课堂名称和出现时间。聪明的学霸猫是非常擅长学习的,即使在打盹的时候,也是在学习。它在某个课堂停留的时间越长,学习效果就越好。请你计算一下它哪门课学的最好吧(我不会告诉你它经常去听金老师的高等数学哟)。
输入
输入有多行。
每行包含三个数据,分别表示课堂名称(长度不超过30个字符),学霸猫的出现时间和离开时间,这两个时间都是指同一天。课堂名称保证不重复。
输出
输出学霸猫学习效果最好的一门课的名称和时长(具体格式见样例输出),占一行,两个数据间以空格分隔,末尾没有空格。
样例输入
programming 14:00 15:30
math 8:00 8:10
样例输出
programming 1:30
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
class Subject{
String name;
String begin;
String over;
int time;
}
public class 学霸猫 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String line = scanner.nextLine();
Subject reSubject = new Subject();
while (!line.equals("")) {
String[] split = line.split(" ");
Subject subject = new Subject();
subject.name = split[0];
subject.begin = split[1];
subject.over = split[2];
String[] split2 = subject.begin.split(":");
String[] split3 = subject.over.split(":");
int timebegin = Integer.valueOf(split2[0])*60+Integer.valueOf(split2[1]);
int timeover = Integer.valueOf(split3[0])*60+Integer.valueOf(split3[1]);
int time = timeover-timebegin;
subject.time = time;
if (time>reSubject.time) {
reSubject = subject;
}
line = scanner.nextLine();
}
String time = reSubject.time/60+":"+ reSubject.time%60;
System.out.println(reSubject.name+" "+time);
}
}
3.递归
https://segmentfault.com/a/1190000038392459
https://developer.51cto.com/art/202007/620693.htm
- 阶乘
- 斐波那契数列
https://zhuanlan.zhihu.com/p/108269159
- 爬楼梯的理解
https://www.jianshu.com/p/74cdb5d8d264
- 汉诺塔
https://blog.csdn.net/liujian20150808/article/details/50793101
* 1.1261: 放苹果
题目描述
把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法。
输入
第一行是测试数据的数目t(0 <= t <= 20)。以下每行均包含二个整数M和N,以空格分开。1<=M,N<=10。
输出
共t行,每行一个整数,表示对应有多少种不同的方法。
样例输入
1
7 3
样例输出
8
import java.util.Scanner;
public class 放苹果 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
for (int i = 0; i < num; i++) {
// String line = scanner.nextLine();
int apple = scanner.nextInt();
int plate = scanner.nextInt();
System.out.println(putApple(apple,plate));
}
}
public static int putApple(int m, int n) {
// 递归出口:有0个苹果 || 只有1个盘子
if (m == 0 || n == 1)
return 1;
if (n>m) // 盘子比较多,肯定有空盘子,去掉必空的盘子
return putApple(m, m);
else // 苹果比较多:
// 1:至少有一个空盘子,拿掉这个空盘子
// 2:每个盘子都有苹果,各拿掉一个苹果(极限是最少的有1个苹果)
return putApple(m, n - 1) + putApple(m - n, n);
}
}
- 递归算法的练习题
https://www.cnblogs.com/liuzhen1995/p/11748881.html
https://zhuanlan.zhihu.com/p/59685884
1.
4.分治
https://blog.csdn.net/mingyuli/article/details/79608871
- 汉诺塔
https://www.jianshu.com/p/c26ce803b187
https://blog.csdn.net/zandaoguang/article/details/76889284
https://www.zhihu.com/question/24385418
public class 汉诺塔 {
public static void main(String[] args) {
hanoiTower(6, 'A', 'B', 'C');
}
/**
* 汉诺塔问题
*
* @param num 有多少层
* @param a 柱子1
* @param b 柱子2
* @param c 柱子3
*/
public static void hanoiTower(int num, char a, char b, char c) {
if (num == 1) {
System.out.println("第1个盘从 " + a + " -> " + c);
} else {
/*
奇数时:
第1个盘子:A-->C
第2个盘子:A-->B
第1个盘子:C-->B
//这是腾出了位置,c空了出来
第3个盘从 A ->C
第1个盘从 B -> A
第2个盘从 B -> C
偶数时:
第1个盘子:A--->B
第2个盘从: A--> C
第1个盘从 B -> C
//这是腾出了位置,b空了出来
第3个盘从 A -> B
第1个盘从 C -> A
*/
hanoiTower(num - 1, a, c, b);
System.out.println("第" + num + "个盘从 " + a + " -> " + c);
hanoiTower(num - 1, b, a, c);
}
}
}
import java.util.Scanner;
public class Hanoi2 {
static int m = 0;// 标记移动次数
// 实现移动的函数
public static void move(int disks, char N, char M) {
System.out.println("第" + (++m) + " 次移动 : " + " 把 " + disks + " 号圆盘从 " + N + " ->移到-> " + M);
}
// 递归实现汉诺塔的函数
public static void hanoi(int n, char A, char B, char C) {
if (n == 1)// 圆盘只有一个时,只需将其从A塔移到C塔
Hanoi2.move(1, A, C);// 将编b号为1的圆盘从A移到C
else
{
// 否则
hanoi(n - 1, A, C, B);// 递归,把A塔上编号1~n-1的圆盘移到B上,以C为辅助塔
Hanoi2.move(n, A, C);// 把A塔上编号为n的圆盘移到C上
hanoi(n - 1, B, A, C);// 递归,把B塔上编号1~n-1的圆盘移到C上,以A为辅助塔
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
char A = 'A';
char B = 'B';
char C = 'C';
System.out.println("******************************************************************************************");
System.out.println("汉诺塔问题(把A塔上编号从小号到大号的圆盘从A塔通过B辅助塔移动到C塔上去---山东科技大学昝道广");
System.out.println("******************************************************************************************");
System.out.print("请输入圆盘的个数:");
int n = in.nextInt();
Hanoi2.hanoi(n, A, B, C);
System.out.println(">>移动了" + m + "次,把A上的圆盘都移动到了C上");
in.close();
}
}
1.1031: 苹果分级
今年老王家的苹果丰收了,为了能卖个好价钱,老王把苹果按直径大小分等级出售。这么多苹果如何快速的分级,可愁坏了老王。现在请你编写一个程序来帮助老王模拟苹果分级的操作吧,要求一级果的直径大于等于70毫米,二级果的直径是6960毫米,三级果的直径是5950毫米,小于50毫米的算四级果。
输入
若干个整数,表示每个苹果的直径,当输入直径小于20时表示结束。苹果的直径最小为20,最大为120。
输出
输出有两行:第一行输出苹果总个数;第二行输出一级果、二级果、三级果、四级果的个数,中间用空格分隔,四级果后面无空格。
样例输入
67 34 85 58 32 54 59 60 55 42 51 0
样例输出
11
1 2 5 3
import java.util.Scanner;
public class 分治算法 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String hang = scanner.nextLine();
int one = 0;
int two = 0;
int three = 0;
int four = 0;
String[] split = hang.split(" ");
for (int i = 0; i < split.length-1; i++) {
int num = Integer.valueOf(split[i]);
if (num>=70) {
one++;
}else if (num>=60) {
two++;
}else if (num>=50) {
three++;
}else {
four++;
}
}
System.out.println(split.length-1);
System.out.println(one+" "+two+" "+three+" "+four);
}
}
5.贪心
1. 1087: 零钱兑换
题目描述
小油瓶拿着100元去买糖吃,买了糖后要找零时,发现店里只剩下1元、2元和5元的纸币了。找回来一大堆零钱确实很烦人,所以小油瓶要求店员找给他的纸币的数量必须是最少的。 已知需要找还的钱的数额,同时店里有充足的1、2、5元纸币供找兑。编写一个程序,计算以最少数量的纸币凑出找零的数额时,各种纸币的使用数量。
输入
程序的输入为若干行,每行为一个整数,每个整数代表每次需找还的零钱的数量n(0<n<100),输入0则代表输入结束。
输出
根据每行输入的需找还的零钱的数量,程序计算相应的最小数量组合,并将纸币的使用数量以1元、2元、5元的顺序在相应行中输出,中间以一个空格相隔,每行输入对应一行输出。
样例输入
8
12
0
样例输出
1 1 1
0 1 2
提示
12元最好的组合为0张1元,1张2元,2张5元,所以对应的输出为0 1 2
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
import javax.print.attribute.standard.NumberUpSupported;
public class 零钱兑换 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<Integer> nums = new LinkedList();
int num = scanner.nextInt();
while (num!=0) {
nums.add(num);
num = scanner.nextInt();
}
for (int i = 0; i < nums.size(); i++) {
num = nums.get(i);
int five = num/5;
int two = num%5/2;
int one = num%5%2;
System.out.println(one+" "+two+" "+five);
}
}
}
6.排序
1.1051: 奥运会跳水比赛
https://www.e-learn.cn/topic/3276295
`
import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;
//定义一个类,用来代表每个选手
class People{
String name;
float[] scores = new float[5];
float nandu;
float sum;
}
public class 奥运会跳水比赛 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
//声明数组
People[] peoples = new People[num];
//消除回车换行的影响
scanner.nextLine();
for (int i = 0; i < num; i++) {
String hang = scanner.nextLine();
String[] split = hang.split(" ");
//数组赋值
peoples[i] = new People();
peoples[i].name = split[0];
//选手得分赋值
for (int j = 1; j < split.length-1; j++) {
peoples[i].scores[j-1] = Float.valueOf(split[j]);
}
//选手成绩排序
Arrays.sort(peoples[i].scores);
//难度系数赋值
peoples[i].nandu = Float.valueOf(split[6]);
// 求出总分
peoples[i].sum = (peoples[i].scores[1]+peoples[i].scores[2]
+peoples[i].scores[3])*peoples[i].nandu;
}
//冒泡排序,求出序号
for (int i = 0; i < peoples.length-1; i++) {
for (int j = 0; j < peoples.length-i-1; j++) {
if (peoples[j].sum<peoples[j+1].sum) {
People people = peoples[j];
peoples[j] = peoples[j+1];
peoples[j+1] = people;
}
}
}
//输出排名。注意保留一位小数
for (int i = 0; i < peoples.length; i++) {
System.out.println(i+1+" "+peoples[i].name+" "+Math.round(peoples[i].sum*10)/10.0);
}
}
}
7.*倍增
- 最近公共祖先(Least Common Ancestors,LCA)问题详解
https://blog.csdn.net/ywcpig/article/details/52336496
- 倍增法
https://blog.csdn.net/blaze003003/article/details/81084954
* 1.小刚传说
https://blog.csdn.net/jeryjeryjery/article/details/52853017
题目描述
众所周知,刘小刚是海亮中学的金牌教练,然而世人并不知道他的传奇经历,以及那个曾经轰动世界的名字sharpland。
2003年,美国研究团队在量子计算机的研制上取得了重大突破,一旦美国成功研发出量子计算机,一切加密手段都将形同虚设。当此之时,国内第一黑客sharpland秘密潜入美国中央情报局,得知关于量子计算机的研究成果封存于五角大楼计算机群之中。经过一周的0Day挖掘,sharpland成功侵入计算机群,却发现这里的文件保护机制非同寻常。
五角大楼计算机群的文件形成了树结构,且树的形态随时间变化。已知初始时刻树上仅有一个根节点1,当成功拷贝结点i上的文件时,树上会新增结点i+1,它的父亲为一个已存在的结点。树的大小增加为n时便会停止。
sharpland通过之前挖掘的0Day成功推算出了所有新增结点的父亲,为了破解文件保护系统,他需要在每次新增结点后新增的结点i和上一次新增的结点i-1的路径长度。
输入
第一行,一个整数n表示最终树的大小。
接下来n-1行,每行一个整数表示新增节点的父亲。
输出
共n-1行,每行一个整数表示答案。
样例输入
【样例1】
6
1
2
2
1
5
【样例2】
10
1
1
3
1
2
3
6
1
8
样例输出
【样例1】
1
1
2
3
1
【样例2】
1
2
1
3
3
4
5
4
5
提示
对于30%的数据,n≤100
对于60%的数据,n≤2000
对于100%的数据, 2≤n≤200000
【后记】
sharpland成功窃取数据的那一刻,中央情报局察觉到了数据失窃并发布全球通缉令,sharpland隐姓埋名逃会国内,以刘小刚为化名,以高中竞赛教练为掩护,生活至今。然而第一黑客sharpland之名早已响彻世界。
2.快速幂
https://www.jianshu.com/p/45a2f9e8391a
快速幂算法推导(详解)
https://blog.csdn.net/Ven21959/article/details/99671654
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-A6tqetFB-1622898105633)(蓝桥杯比赛.assets/20190816103145244.png)]
题意:
计算a^n % b,其中a,b和n都是32位的整数。
样例:
例如 2^31 % 3 = 2
例如 100^1000 % 1000 = 0
挑战:
O(logn)
public class 快速幂算法{
static int power(int a,int b) {
int ans = 1;
// 当b不为0时,继续循环
while(b!=0) {
//把b转为二进制进行运算,如果是偶数,b的最后一位是0,否则就是1,这样就可以判断出基数,偶数
if((b&1)!=0){
ans=ans*a;//若指数为奇数,将分离出来的一次方底数收集好
}
//若指数为偶数数
a=a*a; //底数变为原来的平方
b>>=1; //指数变为原来的一半 .b要转为二进制进行运算
System.out.println(b);
}
return ans;
}
public static void main(String[] args) {
System.out.println(power(3, 10));
}
}
8.构造
https://blog.csdn.net/wtq1993/article/details/52910319
1.*数对
题目描述
给定一个正整数n,现在有一个由数对(a,b)组成的序列,其中1<=a<=n,|b|<=n。|b|表示b的绝对值。该序列称为优美序列,当且仅当以下条件同时满足:
1、所有的数对都不相同。
2、对于每一个有数对(a,b),a和|b|不相同。
3、对于每一个有数对(a,b),若b>0,则它之前一定存在一个数对(a,b
)满足a=b且b
=0;
4、对于每一个有数对(a,b),若b<0,则它之前一定不存在一个数对(a,b
)满足a=-b且b
=0;
5、对于所有相邻的数对(a1,b1),(a2,b2),满足b1和b2不同时为正整数且不同时为负数且不同时为0;
请你求出最长的优美的序列的长度。
例如,当n=2时,其中一个最长的优美的序列为(2,-1), (1,0), (1,-2), (2,1), (2,0), (1,2), 长度为6。
输入
仅一行,一个正整数n。
输出
输出一个整数,如题所述。
样例输入
2
样例输出
6
提示
对于20%的数据,n<=4。
对于80%的数据,n<=106。
对于100%的数据,n<=108。
9.前缀和
1.Tower
题目描述
平面上有N个整数坐标点。如果将点(x0,y0)移动到(x1,y1),则需要的代价为|x0-x1|+|y0-y1|。求使得K(K=1,……,N)个点在同一位置上最少需要的代价。
输入
第一行一个正整数N。
接下来N行,每行两个正整数xi和yi,为第i个点的坐标,不超过106。
输出
输出共N行,第i行为使得有i个点在同一位置的最少代价。
样例输入
4
15 14
15 16
14 15
16 15
样例输出
0
2
3
4
提示
对于100%的数据,满足1≤N≤50。
思路:
找到所有相关点(x,y坐标的界限)所组成的矩形,然后一个个比较,找到最小的值。
import java.util.LinkedList;
import java.util.List;
import java.util.Scanner;
//定义一个结点,代表着坐标
class Node{
int x;
int y;
public Node(int x, int y) {
super();
this.x = x;
this.y = y;
}
}
public class Tower {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int begin = scanner.nextInt();
// 定义一个集合,把所有的点存贮起来
// System.out.println(1);
scanner.nextLine();
List<Node> list = new LinkedList<Node>();
for (int i = 0; i < begin; i++) {
String[] ss = scanner.nextLine().split(" ");
Node node = new Node(Integer.valueOf(ss[0]), Integer.valueOf(ss[1]));
list.add(node);
}
// //初始化区间的值
int minx = list.get(0).x;
int miny = list.get(0).y;
int maxx = list.get(0).x;
int maxy = list.get(0).y;
for (int i = 0; i < begin; i++) {
//每一次遍历,也就代表着一次输出
int x = list.get(i).x;
int y = list.get(i).y;
//代表着代价的最小值
int min = 9999999;
//找到所有的点所在的矩形区间
if (x<minx) {
minx = x;
}
if (y<minx) {
miny = y;
}
if (x>maxx) {
maxx = x;
}
if (y>maxy) {
maxy = y;
}
//开始遍历这个矩形区间上的所有点
for (int j = minx; j <= maxx; j++) {
for (int j2 = miny; j2 <= maxy; j2++) {
//把集合里的点取出来,一一和矩形区间的点相减
//代表着一个临时值
int temp = 0;
for (int k = 0; k<=i; k++) {
temp+=Math.abs(list.get(k).x-j)+Math.abs(list.get(k).y-j2);
}
//在矩形上的这个点的代价是最小的
if(temp<min) {
min = temp;
}
}
}
System.out.println(min);
}
}
}
10.差分
1.Fancy 的区间
省选终于考完了,但是还是不出成绩,Fancy 非常焦急而忧伤的等待着。
闲着无聊的 Fancy 打开书包拿出了一张纸和一支笔,在纸上画了一行n个格子。Fancy 每次想两个数字,然后把这两个数字之间(包括这两个数字)的格子涂黑。如果有格子已经涂过了,Fancy 还会再涂一遍(反正都是黑的)。突然成绩出来了,Fancy 跑去听成绩了,不小心把纸掉在了地上。现在 Fancy 想知道还有哪些区间没有涂黑,你能帮帮她吗?
输入
第一行两个数n和 m,n表示格子数目,m表示区间对数。 接下来m行,每行两个数x和y,表示将x 到y之间的格子涂黑。
输出
输出若干行,每一行两个数x和 y,中间用空格隔开,表示从x到 y 之间是白色的。
注:
1.从x到 y 表示包括x和 y 的中间一整段;
2.输出的区间必须合法(x≤y)且无重复;
3.如果只有一个点x,则输出 x x;
4.输出时区间按左端点排序,且不允许出现前后两个区间可以合并的情况,如 1 3 和 4 5 要输出 1 5;
5.若所有区间都被覆盖,则不用输出;
样例输入
10 3
1 3
2 5
8 9
样例输出
6 7
10 10
提示
对于100%的数据,1≤n≤1000000,1≤m≤500000,1≤x≤y≤n。
import java.util.Scanner;
public class Fancy的区间 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String ss = scanner.nextLine();
String[] ss1 = ss.split(" ");
int n = Integer.valueOf(ss1[0]);
int m = Integer.valueOf(ss1[1]);
//定义一个数组,从一开始计数,末尾多得一个是防止数组越界
int[] arr = new int[n+2];
//在末尾多得那个不能访问
arr[n+1] = 1;
int zuo;
int you;
for (int i = 0; i < m; i++) {
ss = scanner.nextLine();
ss1 = ss.split(" ");
//左区间
zuo = Integer.valueOf(ss1[0]);
//右区间
you = Integer.valueOf(ss1[1]);
//将这些区间里的空间进行赋值,代表不能访问
for (int j = zuo; j <=you; j++) {
arr[j] = 1;
}
}
//开始输出结果,从一开始
for (int i = 1; i <= n; i++) {
if (arr[i] == 0) {
//保证记录
int j = i;
//看看i后面的空间能否访问
while (arr[++i] == 0);
//这样的话代表不能访问,说明它只有一个
if (j == i-1) {
System.out.println(j+" "+j);
return;
}
//这个区间的值都是能访问的
System.out.println(j+" "+(i-1));
}
}
}
}
11.双向搜索
1.数据结构_堆栈_判断回文数
要求:由于输入的一个回文数可能无穷大,所以用单链表存储该数,将用户输入的数以一个单链表的方式存储,从头扫描该单链表,将前面的一半元素入栈,若元素总个数为奇数,则跳过中间的那个元素,然后开始循环:边退栈边在单链表中后移指针,若当前栈顶元素与单链表中当前节点的值域不相等,则退出循环。最后如果栈空且链表比较完毕,则是回文数,否则不是回文数。
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.Stack;
public class 数据结构_堆栈_判断回文数 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String ss = scanner.nextLine();
List list = new ArrayList();
while (!ss.equals("")) {
for (int i = 0; i < ss.length(); i++) {
list.add(ss.charAt(i));
}
ss = scanner.nextLine();
}
Stack stack = new Stack();
int size = list.size();
//有偶数个数字
if (size%2 == 0) {
for (int i = 0; i < size/2; i++) {
stack.push(list.get(i));
}
for (int i = size/2; i < size; i++) {
if (stack.pop() != list.get(i)) {
System.out.println("0");
return;
}
}
System.out.println("1");
}else {
for (int i = 0; i < size/2; i++) {
stack.push(list.get(i));
}
for (int i = size/2+1; i < size; i++) {
if (stack.pop() != list.get(i)) {
System.out.println("0");
return;
}
}
System.out.println("1");
}
}
}