A
按照题意模拟即可
code
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> a(n + 1);
for (int i = 1; i <= n; i++)
cin >> a[i];
cout << a[k] << '\n';
return 0;
}
B
直接双指针即可
假设我们现在的区间是[i, j]
那么可以证明不可能存在一个小于i的数k,能与大于j的数u匹配
所以可以双指针
#include <bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
int n, k, a[N], c[N];
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> k;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= n; i++)
c[i] = c[i - 1] + (a[i] == 0);
int j = 0, res = 0, t1 = n + 1, t2 = n + 1; // 为了处理边界情况而赋值
for (int i = 1; i <= n; i++) {
while (j + 1 <= n && c[j + 1] - c[i - 1] <= k)
j++;
if (res < j - i + 1) {
res = j - i + 1;
t1 = i, t2 = j;
}
}
cout << res << '\n';
for (int i = 1; i <= n; i++)
if (i >= t1 && i <= t2)
cout << 1 << ' ';
else
cout << a[i] << ' ';
return 0;
}
C题
对于每次操作,我们假设新添加的值是x和y
那么我们树的直径只有三种可能,原来的,$a->x$, $b->x$。这里选择$a->y$,$b->y$也是可以的。
之后就简单了,上代码
code
#include <bits/stdc++.h>
using namespace std;
const int N = 1000010, K = 20;
int n, m, f[N][K], d[N];
int lca(int a, int b) {
if (d[a] < d[b])
swap(a, b);
for (int k = K - 1; k >= 0; k--)
if (d[f[a][k]] >= d[b])
a = f[a][k];
if (a == b)
return a;
for (int k = K - 1; k >= 0; k--)
if (f[a][k] != f[b][k])
a = f[a][k], b = f[b][k];
return f[a][0];
}
int get_dist(int a, int b) {
int LCA = lca(a, b);
return d[a] + d[b] - d[LCA] * 2;
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> m;
for (int i = 2; i <= 4; i++)
f[i][0] = 1, d[i] = 1;
n = 4;
int A = 2, B = 3, res = 2;
while (m--) {
int u;
cin >> u;
int x = n + 1, y = n + 2;
n += 2;
d[x] = d[y] = d[u] + 1, f[x][0] = f[y][0] = u;
for (int k = 1; k < K; k++)
f[x][k] = f[f[x][k - 1]][k - 1], f[y][k] = f[f[y][k - 1]][k - 1];
int da = get_dist(A, x), db = get_dist(B, x);
if (da > db && da > res)
res = da, B = x;
else if (da <= db && db > res)
res = db, A = x;
cout << res << '\n';
}
return 0;
}
stO