比赛总结:CF2059 R1002 D2
赛时得分:\(1/6\)
rank:\(10939\)
题目链接:CF2059
PS:赛时被 B 卡了一整场,赛后把 CD 秒了,瞬间红温。反思一下自己为什么会被卡,遇到 Ad-hoc 题就做得慢。
A
设 \(a\) 中不同数的个数为 \(x\),\(b\) 中不同数的个数为 \(y\),无合法方案当且仅当 \(x+y\le 3\),其他情况一定能构造出合法方案。
B
若 \(n=k\),则答案固定。
若 \(n\neq k\),
-
若要使答案是 \(1\),可以在 \(2\le i\le n-(k-2)\) 中找到一个不是 \(1\) 的数,使得它为第二个子数组的第一位,即可。
-
若 \(2\le i\le n-(k-2)\) 都是 \(1\),因为 \(k<n\),所以 \(n-(k-2)\ge 3\),所以中间一定存在 \(\ge 2\) 个 \(1\),直接把 \([1, 1]\) 分配到第二个子数组的前两位,即可使答案为 \(2\)。
因此 \(n\neq k\) 的情况答案 \(\in \{1, 2\}\)。
C
每个队列最多只会操作一次。
那么等价于对每个队列,留下一段后缀和作为它的最终人数。
又因为每一时刻只能操作一次,那么每一列(假设是第 \(j\) 列)最多只能留下一个以 \(a_{i,j}\) 为开头的后缀。
如果我们对 \(a\) 的每一行做后缀和(\(a_{i,n+1}\) 位置的后缀和为 \(0\)),将后缀和数组记为 \(s\),那么原问题等价于从 \(s\) 中选择一些数,使得它们在不同行不同列,要求选出来的数的 \(\operatorname{mex}\) 最大。
重要条件:每个元素都是正整数。
根据这个条件,首先 \(s_{i,n+1}\) 的 \(0\) 一定要选,因为其他地方不会出现 \(0\)。然后 \(s_{i,n}\) 的 \(1\) 一定要选,因为其他地方不会出现 \(1\),······
于是我们发现,只有 \(s_{i,j}=n-j+1\) 的位置是有用的,对应到 \(a\) 就是只有每一行的后缀 \(1\) 是有用的。
那么我们把 \(s\) 的这些位置排个序,贪心的选就好了。
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
const int N = 3e2 + 5, INF = 2e9;
int n;
ll a[N][N];
void Solve() {
cin >> n;
vector<int> rec;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
cin >> a[i][j];
}
a[i][n + 1] = 0;
for (int j = n; j >= 1; j--) {
a[i][j] += a[i][j + 1];
}
for (int j = 1; j <= n + 1; j++) {
if (a[i][j] == n - j + 1) {
rec.push_back(a[i][j]);
break;
}
}
}
sort(rec.begin(), rec.end());
int cur = 0;
for (int i : rec) {
if (i >= cur) cur++;
}
cout << cur << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--) Solve();
return 0;
}
D
存在有限答案,当且仅当 \(s_1\) 可以走到一条边 \((u_1,v_1)\),\(s_2\) 同时可以走到一条边 \((u_2, v_2)\),使得 \(u_1=u_2\),\(v_1=v_2\)。
设 \(dis_{u,v}\) 表示 \(s_1\) 走到 \(u\),\(s_2\) 同时走到 \(v\) 的最小代价,然后 dijkstra 计算最短路即可。
统计答案的时候就 \(O(n^2)\) 枚举一下 \((u,v)\) 即可。
Code
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ull = unsigned long long;
using Pii = pair<int, int>;
const int N = 1e3 + 5, INF = 2e9;
int n, m1, m2, s1, s2;
vector<int> G1[N], G2[N];
int dis[N][N];
bool vis[N][N], E1[N][N], E2[N][N];
struct CMP {
bool operator() (const Pii& a, const Pii& b) const {
return dis[a.first][a.second] > dis[b.first][b.second];
}
};
void dijkstra() {
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
dis[i][j] = INF;
}
}
priority_queue<Pii, vector<Pii>, CMP> pq;
dis[s1][s2] = 0;
pq.emplace(s1, s2);
while (!pq.empty()) {
int u1 = pq.top().first, u2 = pq.top().second;
pq.pop();
if (vis[u1][u2]) continue;
vis[u1][u2] = true;
for (int v1 : G1[u1]) {
for (int v2 : G2[u2]) {
if (dis[v1][v2] > dis[u1][u2] + abs(v1 - v2)) {
dis[v1][v2] = dis[u1][u2] + abs(v1 - v2);
pq.emplace(v1, v2);
}
}
}
}
}
void Solve() {
cin >> n >> s1 >> s2;
cin >> m1;
int u, v;
for (int i = 1; i <= m1; i++) {
cin >> u >> v;
G1[u].push_back(v);
G1[v].push_back(u);
E1[u][v] = E1[v][u] = true;
}
cin >> m2;
for (int i = 1; i <= m2; i++) {
cin >> u >> v;
G2[u].push_back(v);
G2[v].push_back(u);
E2[u][v] = E2[v][u] = true;
}
dijkstra();
int ans = INF;
// cout << "dis:\n";
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
// cout << dis[i][j] << ' ';
if (j != i && E1[i][j] && E2[i][j]) {
ans = min(ans, dis[i][i]);
}
}
// cout << '\n';
}
cout << (ans == INF ? -1 : ans) << '\n';
for (int i = 1; i <= n; i++) {
G1[i].clear();
G2[i].clear();
for (int j = 1; j <= n; j++) {
vis[i][j] = E1[i][j] = E2[i][j] = false;
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin >> T;
while (T--) Solve();
return 0;
}

浙公网安备 33010602011771号