Codeforces Round 541 (Div. 2) 解题报告

对应场次为 CF1131


A. Sea Battle

align 排列,排整齐
adjacent 相邻

题目大意

给定两个矩形的长宽 \(w_1, h_1, w_2, h_2 (1 \le w_1, h_1, w_2, h_2 \le 10^8)\) 然后把两个矩形左边对齐摞在一起
问把这个东西包围一圈要多少个格子

image
image

Solution

首先考虑单个矩形围一圈 显然是 \(2 \times (w + h) + 4\)
然后考虑先把这俩分开然后合一起 看看哪些被撞没了

image

发现显然是 \(2 \times (\min(w_1, w_2) + 2)\)

然后就没了

点击查看代码
/*
*/
#include <bits/stdc++.h>
#define ll long long
using namespace std;

inline int read() {
	int xr = 0, F = 1;
	char cr;
	while (cr = getchar(), cr < '0' || cr > '9') if (cr == '-') F = -1;
	while (cr >= '0' && cr <= '9') 
		xr = (xr << 3) + (xr << 1) + (cr ^ 48), cr = getchar();
	return xr * F;
}

void write(ll x) {
	char ws[51];
	int wt = 0;
	if (x < 0) putchar('-'), x = -x;
	do {
		ws[++wt] = x % 10 + '0';
		x /= 10;
	} while (x);
	for (int i = wt; i; --i) putchar(ws[i]);
}

namespace steven24 {

int w1, h1, w2, h2;

void main() {
	w1 = read(), h1 = read(), w2 = read(), h2 = read();
	int l1 = 2 * (w1 + h1) + 4;
	int l2 = 2 * (w2 + h2) + 4;
	int ans = l1 + l2;
	ans -= (min(w1, w2) + 2) * 2;
	write(ans), putchar('\n');
}

}

int main() {
	steven24::main();
	return 0;
}

B. Draw!

摆烂了不想啃生肉了

题目大意

给定 \(n(1 \le n \le 10^4)\) 个足球赛过程中的比分
询问最多可能会有多少平局

Solution

考虑两次比赛之间两队比分的取值范围 显然为 \(\left[a_{i - 1}, a_i\right]\)\(\left[b_{i - 1}, b_i\right]\)
那么平局就是这两个区间的交
但是通过样例2 我们发现有些比分会被重复计算
所以记一个 \(lst\) 表示上一次计算的比分的右端点 如果这次的左端点与 \(lst\) 相等就给答案-1

点击查看代码
/*
*/
#include <bits/stdc++.h>
#define ll long long
using namespace std;

inline int read() {
	int xr = 0, F = 1;
	char cr;
	while (cr = getchar(), cr < '0' || cr > '9') if (cr == '-') F = -1;
	while (cr >= '0' && cr <= '9') 
		xr = (xr << 3) + (xr << 1) + (cr ^ 48), cr = getchar();
	return xr * F;
}

void write(ll x) {
	char ws[51];
	int wt = 0;
	if (x < 0) putchar('-'), x = -x;
	do {
		ws[++wt] = x % 10 + '0';
		x /= 10;
	} while (x);
	for (int i = wt; i; --i) putchar(ws[i]);
}

namespace steven24 {

const int N = 1e4 + 0721;
int a[N], b[N];
int n, ans;

void main() {
	n = read();
	for (int i = 1; i <= n; ++i) a[i] = read(), b[i] = read();
	ans = 1;
	int lst = 0;
	for (int i = 1; i <= n; ++i) {
		if (min(a[i], b[i]) - max(a[i - 1], b[i - 1]) + 1 <= 0) continue;
		ans += min(a[i], b[i]) - max(a[i - 1], b[i - 1]) + 1;
		if (lst == max(a[i - 1], b[i - 1])) --ans;
		lst = min(a[i], b[i]);
	}
	write(ans), putchar('\n');
}

}

int main() {
	steven24::main();
	return 0;
}


C. Birthday

题目大意

给你 \(n(1 \le n \le 10^2)\) 个数 你可以把它们按任意顺序排成一个环 使得相邻两个元素之差的绝对值最大值最小 输出方案

Solution

起手排序肯定是没啥问题的
然后根据直觉应该是类似于 \(a_1, a_3, a_5, ..., a_6, a_4, a_2\) 这样的山峰形最优
所以直接按这个输出即可

点击查看代码
/*
*/
#include <bits/stdc++.h>
#define ll long long
using namespace std;

inline int read() {
	int xr = 0, F = 1;
	char cr;
	while (cr = getchar(), cr < '0' || cr > '9') if (cr == '-') F = -1;
	while (cr >= '0' && cr <= '9') 
		xr = (xr << 3) + (xr << 1) + (cr ^ 48), cr = getchar();
	return xr * F;
}

void write(ll x) {
	char ws[51];
	int wt = 0;
	if (x < 0) putchar('-'), x = -x;
	do {
		ws[++wt] = x % 10 + '0';
		x /= 10;
	} while (x);
	for (int i = wt; i; --i) putchar(ws[i]);
}

namespace steven24 {

const int N = 521;
int a[N];
int n;

void main() {
	n = read();
	for (int i = 1; i <= n; ++i) a[i] = read();
	sort(a + 1, a + 1 + n);
	for (int i = 1; i <= n; ++i) if (i & 1) write(a[i]), putchar(' ');
	for (int i = n; i; --i) if (!(i & 1)) write(a[i]), putchar(' ');
}

}

int main() {
	steven24::main();
	return 0;
}

D. Gourmet choice

题目大意

给定两个序列的长度 \(n, m(1 \le n, m \le 1000)\) 再给出一个 \(n \times m\) 的矩阵 \(i\)\(j\) 列表示 \(a_i\)\(b_j\) 的大小关系 输出一个构造方案

Solution

做法一:

直接差分约束跑 spfa 稠密图因为 vector 是连续调用比链前快 可以直接艹过去

做法二:

用并查集维护所有相等的变量 然后用有向边维护大小关系
拓扑排序即可

posted @ 2023-10-26 18:59  Steven24  阅读(541)  评论(0)    收藏  举报