「题解」Codeforces Round 891 (Div. 3)
A. Array Coloring
Problem
Sol & Code
只有数列的和为偶数时才符合要求,即有任意个偶数,偶数个奇数。
将这些数分成两部分,发现两部分初始值 \(0\) 为偶数,偶数不会影响奇偶性,故需要偶数个奇数。
#include <bits/stdc++.h>
#define N 51
typedef long long ll;
int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }
int T, n, a[N];
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
int sum = 0;
for (int i = 1 ; i <= n; ++i) {
scanf("%d", &a[i]);
sum += a[i];
}
if (sum & 1) puts("NO");
else puts("YES");
}
return 0;
}
B. Maximum Rounding
Problem
Sol & Code
贪心,尽量进位即可
#include <bits/stdc++.h>
typedef long long ll;
int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }
int T;
std::string s;
int main() {
scanf("%d", &T);
while (T--) {
std::cin >> s;
int n = s.length();
int res = 0, pos = n;
for (int i = n - 1; i >= 0; --i) {
if (s[i] + res - '0' >= 5) res = 1, pos = i;
else res = 0;
}
if (pos == n) std::cout << s << '\n';
else {
for (int i = 0; i < pos - 1; ++i) putchar(s[i]);
if (pos == 0) putchar('1');
else putchar(s[pos - 1] + 1);
for (int i = pos; i < n; ++i) putchar('0');
puts("");
}
}
return 0;
}
C. Assembly via Minimums
Problem
Sol & Code
最小的数出现 \(n-1\) 次,次小的数出现 \(n-2\) 次,依次递推,最大的数取最大值即可,可知答案。
#include <bits/stdc++.h>
#define N 1000001
typedef long long ll;
int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }
int T, n, a[N];
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
int s = n * (n - 1) / 2;
for (int i = 1; i <= s; ++i) scanf("%d", &a[i]);
std::sort(a + 1, a + s + 1);
int now = 1, ad = n - 1;
while (now <= s) {
printf("%d ", a[now]);
now += ad;
--ad;
}
printf("%d\n", a[s]);
}
return 0;
}
D. Strong Vertices
Problem
Sol & Code
讨论两种情况 \(u\) 到 \(v\) 有直接相连的路径有 \(a_u-a_v \geq b_u-b_v\),移相后 \(a_u - b_u \geq a_v - b_v\)。
如果 \(u\) 到 \(w\),\(w\) 到 \(v\) 则有 \(a_u-a_v \geq b_w-b_w,a_w-a_w \geq b_v-b_v\) 相加得 \(a_u-a_v \geq b_u-b_v\),即只要 \(u\) 能到 \(v\) 则有 \(a_u - b_u \geq a_v - b_v\)。
所以答案就是 \(a_u-a_v\) 的值为最大值的那几个。
我 nt 地用了 st。
#include <bits/stdc++.h>
#define N 200001
typedef long long ll;
int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }
int T, n, a[N], b[N], lg[N], ans[N], f[N][21];
int st(int l, int r) {
if (l > r) return -2147483647;
int len = r - l + 1;
return max(f[l][lg[len] - 1], f[r - (1 << (lg[len] - 1)) + 1][lg[len] - 1]);
}
int main() {
scanf("%d", &T);
for (int i = 1; i < N; ++i) {
lg[i] = lg[i - 1] + ((1 << lg[i - 1]) == i);
}
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for (int i = 1; i <= n; ++i) scanf("%d", &b[i]);
for (int i = 1; i <= n; ++i) f[i][0] = a[i] - b[i];
for (int j = 1; (1 << j) <= n; ++j) {
for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
}
}
int cnt = 0;
for (int i = 1; i <= n; ++i) {
if (f[i][0] >= max(st(1, i - 1), st(i + 1, n))) ans[++cnt] = i;
}
printf("%d\n", cnt);
for (int i = 1; i <= cnt; ++i) printf("%d ", ans[i]);
puts("");
}
return 0;
}
E. Power of Points
Problem
Sol & Code
可以发现答案是从这点到所有点的连线的长度和,每次统计答案 \(O(n)\),更新同理。
发现排序后更新只与前后点的数量有关,只需要 \(O(1)\) 更新。
#include <bits/stdc++.h>
#define N 200001
typedef long long ll;
int min(int a, int b) { return a < b ? a : b; }
int max(int a, int b) { return a > b ? a : b; }
int T, n;
ll ans[N];
struct point {
int x, id;
friend bool operator < (point p1, point p2) {
return p1.x < p2.x;
}
}p[N];
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &p[i].x);
p[i].id = i;
}
std::sort(p + 1, p + n + 1);
ans[p[1].id] = 0;
for (int i = 1; i <= n; ++i) ans[p[1].id] += std::abs(p[1].x - p[i].x) + 1;
for (int i = 2; i <= n; ++i) {
if (p[i].x != p[i - 1].x) {
ans[p[i].id] = ans[p[i - 1].id] + 1ll * (p[i].x - p[i - 1].x) * (i - 1) - 1ll * (p[i].x - p[i - 1].x) * (n - i + 1);
} else ans[p[i].id] = ans[p[i - 1].id];
}
for (int i = 1; i <= n; ++i) printf("%lld ", ans[i]);
puts("");
}
return 0;
}