ABC327现场
看到我的名字颜色了么?这就是我的实力,嗯对我是个菜逼/oh/oh/oh
EF做太慢了,前四题发挥稳定没吃罚时。
A
题意:给定一个长度为 \(n\) 的字符串 \(s\),问他是否存在一对相邻的字母 'a' 和 'b'?\(1\leq n\leq 100\)。
Solution
暴力枚举就行,十分的 low IQ。
\(\\\)
Code
// stODDDDDDDDDDDDDDDDDDDDDDDDDDD hzt CCCCCCCCCCCCCCCCCCCCCCCCCOrz
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int kN = 100 + 1;
int n;
string s;
int main() {
cin.tie(0)->sync_with_stdio(0);
cin >> n >> s;
bool t = 0;
for (int i = 0; i < s.size() - 1; i++) {
if (s[i] == 'a' && s[i + 1] == 'b' || s[i] == 'b' && s[i + 1] == 'a') {
t = 1;
}
}
if (t) {
cout << "Yes\n";
} else {
cout << "No\n";
}
return 0;
}
B
题意:给定一个整数 \(n\),问是否存在一个 \(k\) 使 \(k^k = n\)。\(1\leq n\leq 10^{18}\)。
Solution
发现 \(k\) 非常小,暴力枚举即可。
\(\\\)
Code
// stODDDDDDDDDDDDDDDDDDDDDDDDDDD hzt CCCCCCCCCCCCCCCCCCCCCCCCCOrz
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
using LL = long long;
using PII = pair<int, int>;
LL n;
int main() {
cin.tie(0)->sync_with_stdio(0);
cin >> n;
LL w = 1;
for (int i = 1; i <= 100; i++) {
w = 1;
for (int j = 1; j <= i; j++) {
w *= i;
}
if (w == n) {
cout << i << '\n';
return 0;
} else if (w > n) {
cout << "-1\n";
return 0;
}
}
return 0;
}
C
题意:给定一个九宫格,问是否能使每行、每列、每宫格中 \(1~9\) 分别正好出现一次。
Solution
暴力枚举即可。ABC 特有的纯码量题。
\(\\\)
Code
// stODDDDDDDDDDDDDDDDDDDDDDDDDDD hzt CCCCCCCCCCCCCCCCCCCCCCCCCOrz
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int kN = 9 + 1;
int a[kN][kN];
int t[kN];
int main() {
cin.tie(0)->sync_with_stdio(0);
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= 9; j++) {
cin >> a[i][j];
}
}
bool f = 1;
for (int i = 1; i <= 9 && f; i++) {
fill_n(t + 1, 9, 0);
for (int j = 1; j <= 9; j++) {
t[a[i][j]] = 1;
}
for (int j = 1; j <= 9; j++) {
f &= t[j];
}
}
for (int i = 1; i <= 9 && f; i++) {
fill_n(t + 1, 9, 0);
for (int j = 1; j <= 9; j++) {
t[a[j][i]] = 1;
}
for (int j = 1; j <= 9; j++) {
f &= t[j];
}
}
for (int i = 1; i <= 9 && f; i += 3) {
for (int j = 1; j <= 9 && f; j += 3) {
fill_n(t + 1, 9, 0);
for (int k = i; k <= i + 2; k++) {
for (int l = j; l <= j + 2; l++) {
t[a[k][l]] = 1;
}
}
for (int k = 1; k <= 9; k++) {
f &= t[k];
}
}
}
if (f) {
cout << "Yes\n";
} else {
cout << "No\n";
}
return 0;
}
D
题意:给定两个长度为 \(m\) 的序列 \(a\) 和 \(b\),序列中每个数大小不超过 \(n\),问是否存在一个长度为 \(n\) 的 01 序列 \(x\),使对于所有 \(1\leq i\leq m\),有 \(x_{a_i}\) != \(x_{b_i}\)。\(1\leq n, m\leq 2\times 10^5\)。
我的 blog 不知道为什么 Latex 渲染 \(\neq\) 会出锅,只能 != 看了。
Solution
题面说到 \(x\) 是个 01 序列实际上就已经明示了它是个二分图:\(x_{a_i}\) != \(x_{b_i}\) 相当于连边 \(a_i\ to\ b_i\) 染色,因为 \(x\) 的值只能是 0 或 1,所以这个题就变成了二分图的判定。这里我不想写染色法,就随便写了个并查集,结果写了个 "f[x] = F(x)",还调了一两分钟。
\(\\\)
Code
// stODDDDDDDDDDDDDDDDDDDDDDDDDDD hzt CCCCCCCCCCCCCCCCCCCCCCCCCOrz
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int kN = 2e5 + 1;
int n, m;
int a[kN], b[kN];
int fa[2 * kN];
int R(int x) {
if (fa[x] == x) {
return x;
}
fa[x] = R(fa[x]);
return fa[x];
}
void M(int x, int y) {
x = R(x), y = R(y);
if (x == y) {
return;
}
fa[x] = y;
}
int main() {
cin.tie(0)->sync_with_stdio(0);
cin >> n >> m;
for (int i = 1; i <= m; i++) {
cin >> a[i];
}
for (int i = 1; i <= m; i++) {
cin >> b[i];
}
iota(fa, fa + 2 * n + 1, 0);
for (int i = 1; i <= m; i++) {
M(a[i], b[i] + n);
M(a[i] + n, b[i]);
}
for (int i = 1; i <= n; i++) {
if (R(i) == R(i + n)) {
cout << "No\n";
return 0;
}
}
cout << "Yes\n";
return 0;
}
E
题意:给定一个长度为 \(n\) 的序列 \(p\),你可以从中选出一个长度为 \(k\) 的子序列 \(q\)(\(k\) 可以自选),一个子序列的权值 \(R\) 表示如下:
求所有子序列中 \(R\) 的最大值。*子序列不可打乱顺序。\(1\leq n\leq 5000\)。
Solution
你感觉这个 \((0.9)^{k-i}\) 很烦,因为 \(k\) 的不确定他的值也无法确定。然而可以直接倒着做。设 \(f_{i, j}\) 表示考虑了后 \(i\) 个数,选了 \(j\) 个数的答案最大值,根据定义转移就有 \(f_{i, j} = \max(f_{i + 1, j}, f_{i + 1, j - 1} + (0.9)^{j - 1} p_i)\)。时间复杂度 \(O(n^2)\),足以通过此题。
\(\\\)
Code
// stODDDDDDDDDDDDDDDDDDDDDDDDDDD hzt CCCCCCCCCCCCCCCCCCCCCCCCCOrz
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int kN = 5e3 + 2;
constexpr double kI = 1e18;
int n;
int p[kN];
double f[kN][kN], p9[kN];
int main() {
cin.tie(0)->sync_with_stdio(0);
cin >> n, p9[0] = 1;
for (int i = 1; i <= n; i++) {
cin >> p[i];
p9[i] = 0.9 * p9[i - 1];
}
fill(f[0], f[n + 1] + n + 2, -kI);
f[n + 1][0] = 0;
for (int i = n; i >= 1; i--) {
f[i][0] = 0;
for (int j = 1; j <= n; j++) {
// f[i][j] = f[i + 1][j];
f[i][j] = max(f[i + 1][j], f[i + 1][j - 1] + p9[j - 1] * p[i]);
}
}
double ans = -kI, s = 0;
for (int i = 1; i <= n; i++) {
s += p9[i - 1];
ans = max(ans, f[1][i] / s - 1200.0 / sqrt(i));
}
cout << fixed << setprecision(8) << ans << '\n';
return 0;
}
F
题意:给定两个长度为 \(n\) 的序列 \(x_i\) 和 \(t_i\),表示第 \(i\) 个苹果将在 \(t_i\) 时落在 \(x_i\) 上。你可以选择一段长度为 \(w-1\) 的位置区间和一段长度为 \(d-1\) 的时间区间。问最多有多少个苹果在你选定的时间与位置区间内落下。\(1\leq n, d, w, t_i, x_i \leq 2\times 10^5\)。
Solution
你把位置看作一维,时间看作另一维,这个问题就转化为了固定矩形长宽的矩形最多点覆盖问题板子。线段树维护一下即可。
\(\\\)
Code
// stODDDDDDDDDDDDDDDDDDDDDDDDDDD hzt CCCCCCCCCCCCCCCCCCCCCCCCCOrz
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
using LL = long long;
using PII = pair<int, int>;
constexpr int kN = 2e5 + 5;
struct Tree {
int w, t;
} t[4 * kN];
void PU(int x) { t[x].w = max(t[2 * x].w, t[2 * x + 1].w); }
void PD(int x) {
if (!t[x].t) {
return;
}
t[2 * x].t += t[x].t, t[2 * x].w += t[x].t;
t[2 * x + 1].t += t[x].t, t[2 * x + 1].w += t[x].t;
t[x].t = 0;
}
void U(int L, int R, int w, int x, int l, int r) {
if (R < l || r < L) {
return;
} else if (L <= l && r <= R) {
t[x].w += w, t[x].t += w;
return;
}
int m = (l + r) / 2;
PD(x);
U(L, R, w, x * 2, l, m);
U(L, R, w, x * 2 + 1, m + 1, r);
PU(x);
}
struct Node {
int x, y, f;
bool operator<(const Node& a) const { return PII(x, f) < PII(a.x, a.f); }
} a[2 * kN];
int n, d, h;
int main() {
cin.tie(0)->sync_with_stdio(0);
cin >> n >> d >> h, d--, h--;
int tot = 0, L = 1e9, R = 0;
for (int i = 1, x, y; i <= n; i++) {
cin >> x >> y;
L = min(L, y), R = max(R, y);
a[++tot] = {x, y, 1}, a[++tot] = {x + d + 1, y, -1};
}
sort(a + 1, a + tot + 1);
int ans = 0;
for (int i = 1; i <= tot; i++) {
int l = max(L, a[i].y), r = min(R, a[i].y + h);
U(l, r, a[i].f, 1, L, R);
ans = max(ans, t[1].w);
}
cout << ans << '\n';
return 0;
}
G 我是真的不会,这就是 ABC 革新后的难度跨度么?