CF2031A. Penchick and Modern Monument

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <bits/stdc++.h>
using namespace std;

int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> cnt(n);
for (int i = 0; i < n; i++) {
int x;
cin >> x;
x--;
cnt[x]++;
}
int maxx = 0;
for (int i = 0; i < n; i++) {
maxx = max(maxx, cnt[i]);
}
cout << (n - maxx) << endl;
}
return 0;
}

CF2031B. Penchick and Satay Sticks

每个数只会交换一次,模拟所有交换然后判断是否合法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <bits/stdc++.h>
using namespace std;

int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = 1; i < n; i++) {
if (a[i] == a[i - 1] - 1) {
swap(a[i], a[i - 1]);
}
}
cout << (is_sorted(a.begin(), a.end()) ? "YES" : "NO") << endl;
}
return 0;
}

CF2031C. Penchick and BBQ Buns

偶数的答案显然。对于奇数,必然有一个数出现三次,其下标之差是勾股数,最小的勾股数是 $3^{2}+4^{2}=5^{2}$,最靠近的三个下标是 $1,10,26$,因此如果 $n$ 是小于 $27$ 的奇数就无解。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <bits/stdc++.h>
using namespace std;

int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
if (n % 2 == 0) {
for (int i = 0; i < n / 2; i++) {
cout << (i + 1) << " " << (i + 1) << " ";
}
cout << endl;
} else if (n < 27) {
cout << "-1\n";
} else {
cout << "1 2 3 3 1 ";
for (int i = 0; i < 6; i++) {
cout << (i + 4) << " " << (i + 4) << " ";
}
cout << "2 ";
for (int i = 0; i < 4; i++) {
cout << (i + 10) << " " << (i + 10) << " ";
}
cout << "2 ";
for (int i = 0; i < (n - 27) / 2; i++) {
cout << (i + 14) << " " << (i + 14) << " ";
}
cout << endl;
}
}
return 0;
}

CF2031D. Penchick and Desert Rabbit

对于某两个相邻连通块 $L,R$,如果 $L$ 的最大值比 $R$ 的最小值小,那么 $R$ 的任意点就能够走到 $L$ 的任意点。连通 $L,R$,并将 $R$ 的答案更新为 $L$ 的最大值。

用并查集维护所有的连通块。由于每个连通块都是区间,也可以用栈维护。时间复杂度 $\Theta(n)$。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <bits/stdc++.h>
using namespace std;

int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<array<int, 3>> stk;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
auto [minn, maxx, len] = array{ x, x, 1 };
while (!stk.empty() && stk.back()[1] > minn) {
minn = min(minn, stk.back()[0]);
maxx = max(maxx, stk.back()[1]);
len += stk.back()[2];
stk.pop_back();
}
stk.push_back({ minn, maxx, len });
}
for (auto [minn, maxx, len] : stk) {
for (int i = 0; i < len; i++) {
cout << maxx << " ";
}
}
cout << "\n";
}
return 0;
}

CF2031E. Penchick and Chloe’s Trees

设 $u$ 子树对应的二叉树最低高度为 $h_{u}$。

  • 一方面,$h{u} \geqslant h{v}+1$;

  • 另一方面,$2^{h{u}}$ 应当大于等于 $\sum 2^{h{v}}$,且 $h_{u}$ 尽量小。

因此转移方程为

维护所有 $2$ 的幂次,模拟加法。时间复杂度 $\Theta(n\log n)$。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <bits/stdc++.h>
using namespace std;

int main() {
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
vector<int> p(n);
for (int i = 1; i < n; i++) {
cin >> p[i];
p[i]--;
}
vector<priority_queue<int, vector<int>, greater<>>> Q(n);
vector<int> h(n);
for (int i = n - 1; i >= 0; i--) {
while (Q[i].size() > 1) {
int x = Q[i].top(); Q[i].pop();
int y = Q[i].top(); Q[i].pop();
Q[i].push(max(x, y) + 1);
}
h[i] = max(h[i], Q[i].empty() ? 0 : Q[i].top());
if (i) {
Q[p[i]].push(h[i]);
h[p[i]] = max(h[p[i]], h[i] + 1);
}
}
cout << h[0] << endl;
}
return 0;
}