A - Sort the Subarray
大致题义:Monocarp有一个包含n个整数的数组a。他决定选择两个整数l和r,使1< 2rn,然后对子数组进行排序。子数组a[1 ..]R]是数组a中包含元素a1, al+1, al+2,…的部分。, ar-1, ar)按非降序排列。在对子数组进行排序之后,Monocarp获得了一个新的数组,我们用'表示。例如,如果a =[6,7,3,4,4,4,6,5],并且Monocarp选择了l = 2,r = 5,那么a' =[6,3,4,4,7,6,5]。已知数组a和a'找出Monocarp可能选择的整数l和r。如果有多对值(l,r),找到与最长子数组对应的值。
题解:找到不同的元素的位置并向左右两边寻找边界。输出边界。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
while (t-- != 0) {
int tempL = -1, l = -1, tempR = -1, r = -1;
int len = sc.nextInt();
int[] a = new int[len];
int[] b = new int[len];
// 输入A数组
for (int i = 0; i < len; i++) {
a[i] = sc.nextInt();
}
for (int i = 0; i < len; i++) {
b[i] = sc.nextInt();
// 获取范围最小的边界
if (a[i] != b[i])
if (l == -1)
l = i;
else
r = i;
}
// 从边界出发,寻找真正边界
while (l > 0) {
if (b[l-1] <= b[l])
l --;
else
break;
}
while (r + 1 < len) {
if (b[r] <= b[r+1])
r ++;
else
break;
}
// 打印序号,下标要加一
System.out.println(++l + " " + ++r);
}
}
}
B - Tear It Apart
大致题义:
给你一个字符串 s,由小写拉丁字母组成。
在一个操作中,可以选择其中的多个(一个或多个)位置,以便没有两个选定的位置彼此相邻。然后,从字符串中删除所选位置上的字母。生成的零件在不更改其顺序的情况下连接。
制作所有字母所需的最小操作数是多少 s 一样?
题解:
贪心思想。将 26 个字母都算一遍,求最小值。因为消除的字符不能连续,也就是天然的将每种字符分隔。然后目标就是消除分隔内的字符串,求得最小的消除次数。每次操作只需要算出每段区间中最长的区间,设区间长度为len,最少需要的操作次数为1 + log2^len。Java中没有以2为底的log,所以需要用到换底公式。
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
sc.nextLine();
while (t-- != 0) {
ArrayList<ArrayList<Integer>> arrayLists = new ArrayList<>();
for (int i = 0; i < 26; i++) {
arrayLists.add(new ArrayList<>());
}
String s = sc.nextLine();
StringBuilder stringBuilder = new StringBuilder(s);
for (int i = 0; i < stringBuilder.length(); i++) {
char c = stringBuilder.charAt(i);
arrayLists.get(c - 'a').add(i);
}
int ans = 1 << 30;
for (int i = 0; i < 26; i++) {
ArrayList<Integer> integers = arrayLists.get(i);
// 边界 用于判断最后一个对呀的字母到边界有多少字母
integers.add(stringBuilder.length());
int temp = -1, m = 0;
for (Integer integer : integers) {
m = (int) Math.max(m, Math.log(integer - temp - 1) / Math.log(2) + 1);
temp = integer;
}
ans = Math.min(ans, m);
}
System.out.println(ans);
}
}
}
C - Yura's New Name
大致题义:
在举办了一次团体比赛后,男孩Yura非常疲惫,想改变自己的生活,搬到日本。为了纪念这样的变化,尤拉将他的名字改成了好听的名字。
被这个想法迷住了,他已经想出了一个名字。s仅由字符“”和(“^”组成。但有一个问题――尤拉喜欢笑脸“A八)1和“^^”。因此,该名称的任何字符都必须是至少一个此类笑脸的一部分。请注意,只有名称的连续字符才能是笑脸。
更正式地说,考虑字符串中字符串“^_^"和“^^”的所有匹配项s.那么所有这些事件都必须覆盖整个字符串s,可能与交叉点。例如,在字符串fA_1M_A_^”中,位置的字符3,4,9,10和11不包含在任何笑脸中,其他角色在位置1,2,5,6,7和8包含在笑脸内。
在一个操作中,Jura可以在他的名字中插入一个字符“_”和"”s(您可以将其插入字符串中的任何位置)。他要求你告诉他你需要做的最少操作次数,以使这个名字符合尤拉的标准。
题解:
如注释
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
sc.nextLine();
while (t-- != 0) {
String s = sc.nextLine();
char[] chars = s.toCharArray();
int ans = 0;
// 必须以 '^' 开头
if (chars[0] != '^')
ans ++;
// 碰到了连续两个 '_' 则插入一个 '^'
for (int i = 0; i < chars.length - 1; i++) {
if (chars[i] == '_' && chars[i+1] != '^')
ans ++;
}
// 如果最后一个字符为'_',则需要在最后插入 '^'
// 最后一个字符为 '^',则只要前面有字符就可以组成“笑脸”
if (chars[chars.length-1] == '_')
ans ++;
// 考虑特殊情况,长度为 1,且为'^'
else if (chars.length == 1)
ans ++;
System.out.println(ans);
}
}
}
F - Li Hua and Maze
水题一道~
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
sc.nextLine();
while (t-- != 0) {
int n = sc.nextInt();
int m = sc.nextInt();
int x1 = sc.nextInt();
int y1 = sc.nextInt();
int x2 = sc.nextInt();
int y2 = sc.nextInt();
System.out.println(Math.min(fun(n, m, x1, y1), fun(n, m, x2, y2)));
}
}
static int fun(int n, int m, int x, int y) {
if (x == 1 || x == n) {
if (y == 1 || y == m)
return 2;
return 3;
}
if (y == 1 || y == m) {
return 3;
}
return 4;
}
}