今日校赛在数据和题面上存在太多问题,给诸位道歉!A-E题出题人将自己简易代码发出供大家拷打,F-I等出题人整理之后再另外发出!对于大家心情和参赛体验的破坏,再次表示歉意!剩余题目整理出来后会补充发布。
A 最小半径
读取每个圆的数据,以其中一点为圆心,两点之间连线为半径画出一个圆。这两点都是在X轴上的,所以将这两点的横坐标相减取绝对值就是该圆半径。结果为这n个圆半径最小值。
参考代码
C/C++
#include<bits/stdc++.h>
using namespace std;
int n, res, x1, x2;
int main()
{
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
res = INT_MAX;
for(int i = 1; i <= n; ++i)
{
// 读入每组数据,计算最小值
cin >> x1 >> x2;
res = min(abs(x1 - x2), res);
}
cout << res;
}
Java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int res = Integer.MAX_VALUE;
int x1, x2;
for(int i = 1; i <= n; ++i) {
x1 = sc.nextInt();
x2 = sc.nextInt();
res = Math.min(res, Math.abs(x1 - x2));
}
System.out.println(res);
}
}
B H老师的竞赛宣讲
模拟 + 排序即可。 提交次数中是包含错误提交和正确提交的。
参考代码
C/C++
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
typedef long long ll;
class Player
{
public:
int nums, whole, id, rank;
} players[N];
int n, m;
int cmp1(Player p1, Player p2)
{
return p1.nums == p2.nums ? p1.whole < p2.whole : p1.nums > p2.nums;
}
int cmp2(Player p1, Player p2)
{
return p1.id < p2.id;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
int i, j;
for(i = 1; i <= m; ++i)
{
players[i].nums = 0, players[i].whole = 0, players[i].id = i;
for(j = 1; j <= n; ++j)
{
int x, y, z;
cin >> x >> y >> z;
if(z == 1)
{
players[i].nums++;
players[i].whole += (x - 1) * 20 + y;
}
}
}
sort(players + 1, players + m + 1, cmp1);
players[1].rank = 1;
for(i = 2; i <= m; ++i)
{
if(players[i].nums == players[i - 1].nums && players[i].whole == players[i - 1].whole)
{
players[i].rank = players[i - 1].rank;
}
else
players[i].rank = i;
}
sort(players + 1, players + m + 1, cmp2);
for(i = 1; i <= m; ++i) cout << players[i].rank << '\n' << players[i].nums << '\n' << players[i].whole << '\n';
}
Java
import java.util.Arrays;
import java.io.*;
public class Main {
// 快速输出对象
static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
public static void main(String[] args) {
Scanner sc = new Scanner();
int n = sc.nextInt(), m = sc.nextInt();
student[] students = new student[m];
for (int i = 0; i < m; i++) {
students[i] = new student();
students[i].nums = i+1;
for (int j = 0; j < n; j++) {
int x = sc.nextInt(), y = sc.nextInt();
boolean isValid = sc.nextInt()== 1;
if (isValid) {
students[i].time += (x - 1) * 20 + y;
students[i].amount++;
}
}
}
Arrays.sort(students, (i1, i2) -> i1.amount == i2.amount ? i1.time - i2.time : i2.amount-i1.amount);
students[0].rank = 1;
for (int i = 1; i < m; i++) {
if (students[i].amount == students[i - 1].amount&&students[i].time == students[i - 1].time) {
students[i].rank = students[i - 1].rank;
} else {
students[i].rank = i+1;
}
}
Arrays.sort(students, (i1, i2) -> i1.nums - i2.nums);
for (int i = 0; i < students.length; i++) {
out.println(students[i].rank + "\n" + students[i].amount + "\n" + students[i].time);
}
out.flush();
}
}
class student {
int time, amount, nums, rank;// 耗时,数量,序号,排名
}
class Scanner {
static StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
// 字符串快速读入对象
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public int nextInt() {
try {
st.nextToken();
return (int) st.nval;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public double nextDouble() {
try {
st.nextToken();
} catch (IOException e) {
throw new RuntimeException(e);
}
return st.nval;
}
public float nextFloat() {
try {
st.nextToken();
} catch (IOException e) {
throw new RuntimeException(e);
}
return (float) st.nval;
}
public long nextLong() {
try {
st.nextToken();
} catch (IOException e) {
throw new RuntimeException(e);
}
return (long) st.nval;
}
public String next() {
try {
st.nextToken();
} catch (IOException e) {
throw new RuntimeException(e);
}
return st.sval;
}
// 按行读入字符串
public String readLine() {
String s = null;
try {
s = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return s;
}
}
C 李渊的准备
一个标准RMQ问题。可以用st表或者线段树等方法解决,参考代码给出的是ST表写法。
参考代码
C/C++
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e6 + 3;
int n, t, q ,arr[N][32];
int query(int l, int r)
{
int k = (int)(log((r - l + 1) * 1.0) / log(2.0));
return max(arr[l][k], arr[r - (1 << k) + 1][k]);
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> t >> q;
for (int i = 1; i <= n; ++i)
cin >> arr[i][0];
for (int j = 1; j <= (int)(log(n * 1.0) / log(2.0)); ++j)
{
for (int i = 1; i + (1 << j) - 1 <= n; ++i)
{
arr[i][j] = max(arr[i][j - 1], arr[i + (1 << (j - 1))][j - 1]);
}
}
while (t--)
{
int l, r;
cin >> l >> r;
int res = query(l, r);
string flag = res >= q ? "YES\n" : "NO\n";
cout << res << " " << flag;
}
}
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e6 + 3;
int n, t, q ,arr[N][32];
int query(int l, int r)
{
int k = (int)(log((r - l + 1) * 1.0) / log(2.0));
return max(arr[l][k], arr[r - (1 << k) + 1][k]);
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> t >> q;
for (int i = 1; i <= n; ++i)
cin >> arr[i][0];
for (int j = 1; j <= (int)(log(n * 1.0) / log(2.0)); ++j)
{
for (int i = 1; i + (1 << j) - 1 <= n; ++i)
{
arr[i][j] = max(arr[i][j - 1], arr[i + (1 << (j - 1))][j - 1]);
}
}
while (t--)
{
int l, r;
cin >> l >> r;
int res = query(l, r);
string flag = res >= q ? "YES\n" : "NO\n";
cout << res << " " << flag;
}
}
Java
import java.util.Scanner;
public class Main {
static int n, t, q;
static int maxLog;
static int[] logn;
static int[][] arr;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
t = sc.nextInt();
q = sc.nextInt();
arr = new int[n + 5][22];
logn = new int[n + 5];
// 预处理log
logn[1] = 0;
logn[2] = 1;
for (int i = 3; i <= n; i++) {
logn[i] = logn[i / 2] + 1;
}
maxLog = logn[n];
// 读入
for(int i = 1; i <= n; ++i) arr[i][0] = sc.nextInt();
// 计算
for (int j = 1; j <= maxLog; ++j) {
for(int i = 1; i + (1 << j) - 1 <= n; ++i) {
arr[i][j] = Math.max(arr[i][j - 1], arr[i + (1 << (j - 1))][j - 1]);
}
}
for(int i = 1; i <= t; ++i) {
int l = sc.nextInt();
int r = sc.nextInt();
int s = logn[r - l + 1];
int res = Math.max(arr[l][s], arr[r - (1 << s) + 1][s]);
if (res >= q) {
System.out.println(res + " YES");
} else {
System.out.println(res + " NO");
}
}
}
}
D 猫狗站队
这题出题思路是状压DP,思路来源是牛客周赛的Round32 F 小红的矩阵修改。比赛前期由于出题人std存在严重错误,给大家带来极其不好的体验。赛时经过提醒已经修改了std和测试样例,并发起了重测。
三种狗分别用0 - 1 - 2 表示,猫用 3 表示,则对于每一列,可能的情况就是四进制的 0000-3333,共 256 种情况。对于其中一列,需要确保每一位的值与相邻的值不重复(可以有相邻的3)。依次列举每一列,在判断当前列合法的情况下再去枚举上一列的状态,判断是否冲突。
最终,将最后一列各种状态的可能情况相加。
数据比较大注意开 long long
,此处相邻指的在一个矩阵中上下左右四个方向而不是八个方向。
参考代码
C/C++
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int M = 15, S = 260;
/*
所有状态0000-3333 共4 ^ 4 种->256
*/
int n, m;
ll f[M][S];
int p4[5] = {1, 4, 16, 64, 256};
int b[4] = {};
// 用于检测当前列是否是合法方案
int check(int x)
{
for(int i = 0; i < n; ++i)
{
b[i] = x % 4;
x /= 4;
}
for(int i = 1; i < n; ++i)
{
// 如果有猫,肯定方案合法
if(b[i] == 3) continue;
// 如果有两个一样的狗,就不合法
if(b[i] == b[i - 1]) return 0;
}
return 1;
}
int check(int x, int y)
{
for(int i = 0; i < n; ++i)
{
int x_1 = x % 4, y_1 = y % 4;
x /= 4;
y /= 4;
if(x_1 == 3 || y_1 == 3) continue;
if(x_1 == y_1) return 0;
}
return 1;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
int i, j, k;
// 初始化第一列
for (i = 0; i < p4[n]; ++i)
{
if (check(i))
{
f[0][i] = 1;
}
}
// 枚举后面每一列
for(i = 1; i < m; ++i)
{
// 枚举该列状态
for(j = 0; j < p4[n]; ++j)
{
// 在当前列合法,再去检查与前面一列是否冲突
if(check(j))
{
for(k = 0; k < p4[n]; ++k)
{
if(check(k, j))
{
f[i][j] += f[i - 1][k];
}
}
}
}
}
ll res = 0;
for(i = 0; i < p4[n]; ++i)
{
res += f[m - 1][i];
}
cout << res;
}
Java
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
static int n, m;
static BigInteger[][] f;
static int[] b;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
n = scanner.nextInt();
m = scanner.nextInt();
int[] p4 = new int[]{1, 4, 16, 64, 256};
int S = p4[n];
f = new BigInteger[m][S];
b = new int[4];
for (int i = 0; i < m; ++i) {
for (int j = 0; j < S; ++j) {
f[i][j] = new BigInteger("0");
}
}
// 初始化第一列
for (int i = 0; i < S; ++i) {
if (check(i)) {
f[0][i] = BigInteger.ONE;
}
}
// 枚举后面每一列
for (int i = 1; i < m; ++i) {
// 枚举该列状态
for (int j = 0; j < S; ++j) {
// 在当前列合法,再去检查与前面一列是否冲突
if (check(j)) {
for (int k = 0; k < S; ++k) {
if (check(k, j)) {
f[i][j] = f[i][j].add(f[i - 1][k]);
}
}
}
}
}
BigInteger res = BigInteger.ZERO;
for (int i = 0; i < S; ++i) {
res = res.add(f[m - 1][i]);
}
System.out.println(res);
}
// 用于检测当前列是否是合法方案
static boolean check(int x) {
for (int i = 0; i < n; ++i) {
b[i] = x % 4;
x /= 4;
}
for (int i = 1; i < n; ++i) {
// 如果有猫,肯定方案合法
if (b[i] == 3) continue;
// 如果有两个一样的狗,就不合法
if (b[i] == b[i - 1]) return false;
}
return true;
}
static boolean check(int x, int y) {
for (int i = 0; i < n; ++i) {
int x_1 = x % 4, y_1 = y % 4;
x /= 4;
y /= 4;
if (x_1 == 3 || y_1 == 3) continue;
if (x_1 == y_1) return false;
}
return true;
}
}
E 李渊称帝,踏入神之领域
出题人思路是一个BFS题,前期题面描述上很不清楚。此题参考的是百度之星2023初赛第二场——夏日漫步。
在题目中,李渊在台阶上可以向上或向下移动。但是对于能量波动一样的能量阵,他只能穿梭到上方(编号大的台阶)最近的一个能量阵。
通过以上信息,可以建立一个简单的有向图,而后使用BFS搜索最快到达第n级台阶的情况。
参考代码
C/C++
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
int n, arr[N], vis[N], dis[N];
vector<int> edge[N];
map<int, int> mp;
queue<int> qu;
int bfs()
{
while (!qu.empty())
{
int now = qu.front();
qu.pop();
for (auto y : edge[now])
{
if (y == n)
return dis[now] + 1;
if (vis[y])
continue;
qu.push(y), vis[y] = 1, dis[y] = dis[now] + 1;
}
}
return 0;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; ++i)
{
cin >> arr[i];
if (i != n)
{
edge[i].push_back(i + 1);
edge[i + 1].push_back(i);
}
if (mp.count(arr[i]))
edge[mp[arr[i]]].push_back(i); // 能量值波动一样的
mp[arr[i]] = i;
}
qu.push(1), vis[1] = 1, dis[1] = 0;
cout << bfs();
}
Java
import java.util.*;
public class Main {
static final int N = 200005;
static int n;
static int[] arr = new int[N];
static int[] vis = new int[N];
static int[] dis = new int[N];
static ArrayList<Integer>[] edge = new ArrayList[N];
static Map<Integer, Integer> mp = new HashMap<>();
static Queue<Integer> qu = new LinkedList<>();
static int bfs() {
while (!qu.isEmpty()) {
int now = qu.poll();
for (int y : edge[now]) {
if (y == n)
return dis[now] + 1;
if (vis[y] == 1)
continue;
qu.add(y);
vis[y] = 1;
dis[y] = dis[now] + 1;
}
}
return 0;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for (int i = 1; i <= n; ++i) {
edge[i] = new ArrayList<>();
}
for (int i = 1; i <= n; ++i) {
arr[i] = sc.nextInt();
if (i != n) {
edge[i].add(i + 1);
edge[i + 1].add(i);
}
if (mp.containsKey(arr[i])) {
edge[mp.get(arr[i])].add(i);
}
mp.put(arr[i], i);
}
qu.add(1);
vis[1] = 1;
dis[1] = 0;
System.out.println(bfs());
}
}