A.

模拟题。

B.

马拉车或者 substr+reverse,模拟题。

substr(i, j) 表示从 $i$ 位置开始拿 $j$ 个。

C.

枚举。

D.

考虑建图,然后跑一遍,没有遍历到的就是不确定的点。

E.

用 set 模拟。

F.

定义状态 $dp_{i, x, y}$ 表示到 $i$ 这个位置,正方向还剩下 $x$ 油,负方向还剩下 $y$ 油的最小代价。

最后答案就是 $dp_{i,k,k}$。

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
int lst = 0;
vector<vector<int>> dp(H + 1, vector<int>(H + 1, 0));
for (int i = 0; i < N; i++) {
int d = X[i] - lst;
lst = X[i];

vector<vector<int>> g(H + 1, vector<int>(H + 1, inf));
for (int x = d; x <= H; x++) {
for (int y = d; y <= H; y++) {
cmin(g[x - d][y], dp[x][y - d]);
}
}
dp = move(g);
if (i < N - 1) {
int P, F;
cin >> P >> F;
g = dp;
for (int x = 0; x <= H; x++) {
for (int y = 0; y <= H; y++) {
cmin(g[min(x + F, H)][y], dp[x][y] + P);
cmin(g[x][y], dp[x][min(y + F, H)] + P);
}
}
dp = move(g);
}
}
int ans = inf;
for (int i = 0; i <= H; i++) {
cmin(ans, dp[i][i]);
}

G.

枚举数字,变成一个匹配问题。要找到串的完美匹配,而每个位置每次匹配的权值依次是 $i, i+M. i+2M…$,最小化最大权值。

$p_{c,i}$ 表示数字 $c$ 在第 $i$ 个串里面出现的位置。

然后枚举数字 $c$,再枚举字符串编号 $i$,$j \in p_{c, i}$,考虑左部 $j$ 和右部 $i$ 连边。枚举轮数的时候清空匹配情况,按顺序枚举最大的 $j$,直到匹配数为 $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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
int ans = -1;
for (int c = 0; c < 10; c++) {
debug(c);
vector<vi> adj(M);
vector<int> q;
bool ok = true;
for (int i = 0; i < N; i++) {
if (p[c][i].empty()) {
ok = false;
}
for (auto j : p[c][i]) {
q.pb(j);
adj[j].pb(i);
}
}
if (!ok) {
continue;
}
sort(all(q));
q.resize(unique(all(q)) - q.begin());
int res = 0;
vi mc(N, -1);
vi vis(M);
auto find = [&](auto self, int u) -> bool {
vis[u] = 1;
for (auto v : adj[u]) {
if (mc[v] == -1 || (!vis[mc[v]] && self(self, mc[v]))) {
mc[v] = u;
return true;
}
}
return false;
};
for (int t = 0;; t++) {
for (auto i : q) {
if (find(find, i)) {
res += 1;
if (res == N) {
int v = i + t * M;
if (ans == -1 || ans > v) {
ans = v;
break;
}
}
vis.assign(N, 0);
}
}
if (res == N) {
break;
}
}
}

cout << ans << "\n";