A - Covid-19

签到

AC Code
1
2
3
4
5
6
7
8
9
10
#include "bits/stdc++.h"

int main() {
int p, q;
std::cin >> p >> q;

if (p <= 50 && q <= 10) std::cout << "White\n";
else if (q > 30) std::cout << "Red\n";
else std::cout << "Yellow\n";
}

B - Statistics

要求单调不增,每一步维护前缀的最小值,如果当前值更大,那么就修改之;否则更新最小值。时间复杂度 O(n)O(n).

AC Code
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>

constexpr int N = 1e4 + 10;

int n, a[N];
long long sum = 0;

int main() {
std::cin >> n;
for (int i = 1; i <= n; i++) std::cin >> a[i];

int maxv = a[1];
for (int i = 1; i <= n; i++) {
if (maxv < a[i]) {
sum += a[i] - maxv;
a[i] = maxv;
}
maxv = std::min(maxv, a[i]);
}

std::cout << sum << "\n";
}

C - Science Fiction

考虑按元素从小到大一个一个排序。假设 0t10\sim t-1 已经排序完成,接下来把在 kk 位置上的数排到 tt 上. 由于每次交换的两个数的位置只能有一个 bit 位的差别,所以我们只需要从 lowest bit 往 highest bit 考虑,如果 k,tk,tii-th bit 不一致,那么就交换 ak,ak2ia_k,a_{k\oplus 2^i}. 我们可以证明 k2ik\oplus 2^i 一定不会 <t\lt t(然而我不会证,我是猜的)

所以总的交换次数最多为 O(nlogn)O(n\log n)10×1024<1200010\times 1024\lt 12000.

AC Code
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
35
36
37
38
#include <bits/stdc++.h>
#include <cstdlib>

constexpr int N = (1 << 10) + 10;
int n, a[N], T;
std::map<int, int> p;
std::vector<std::pair<int, int>> ans;

int main() {
std::cin >> n, T = 1 << n;
for (int i = 0; i < T; i++) std::cin >> a[i];
for (int i = 0; i < T; i++) p[a[i]] = i;

int place = 0;
auto get = [&](int v, int i) { return v >> i & 1; };
auto mod = [&](int v, int i) { return v ^ (1 << i); };

for (auto [val, id] : p) {
assert(id >= place);

for (int i = 0; i < n; i++) {
if (get(id, i) != get(place, i)) {
p[val] = mod(id, i);
p[a[mod(id, i)]] = id;
std::swap(a[id], a[mod(id, i)]);
id = mod(id, i);

ans.push_back({id, mod(id, i)});
}
}

place++;
}

assert(ans.size() <= 12000);
std::cout << ans.size() << "\n";
for (auto [i, j] : ans) std::cout << i << " " << j << "\n";
}

L - The Last Supper

因为有时间上的顺序,如果我们定义 dp[i][j]dp[i][j]ii 可以感染 jj,那么考虑

ii1i+1i i\to i-1 \\ i+1\to i

这样会错误地让 i+1i+1 也可以感染 i1i-1 实际上并不行。所以我们定义 dp[i][j]dp[i][j]ii 可以被 jj 感染,这样上述的问题就不存在了. 因为是存在性 DP,所以转移式是(考虑 iji\to j

k,dp[j][k] |= dp[i][k] \forall k, dp[j][k] \texttt{ |= } dp[i][k]

std::bitset 可以优化到 O(qnw)O(\frac{qn}{w}),足以通过此题.

AC Code
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
35
#include <bits/stdc++.h>
constexpr int N = 1e5 + 10;
using bset = std::bitset<N>;

int n, m, q;
int af[N];
bset from[N];

int main() {
std::cin.tie(0)->sync_with_stdio(0);
std::cout.tie(0);

std::cin >> n >> m >> q;
for (int i = 1; i <= m; i++) std::cin >> af[i];
for (int i = 1; i <= n; i++) from[i].set(i);

while (q--) {
int id, next;
char c;

std::cin >> id >> c;
if (c == 'L') next = id == n ? 1 : id + 1;
else next = id == 1 ? n : id - 1;

from[next] |= from[id];
}

bset ans;
for (int i = 1; i <= n; i++) ans.set(i);
for (int i = 1; i <= m; i++) ans &= from[af[i]];

for (int i = 1; i <= n; i++)
if (ans.test(i)) std::cout << i << " ";
std::cout << "\n";
}