Codeforces Round 936 (Div. 2)

A. Median of an Array

题目大意:

  • 你只能对任何一个数进行 +1 操作
  • 问最少需要多少次操作,可以把中位数 a[i] 变成另一个数

思路:

  • 直接倒着枚举即可,因为中位数的位置不会改变,所以只要把当前这个位置后面与它相等的数的个数输出即可

时间复杂度:\(O(n)\)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void solve() {
int n;
std::cin >> n;

std::vector<int> a(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
std::sort(a.begin(), a.end());

std::map<int, int> mp;
for (int i = n - 1; i >= 0; i--) {
mp[a[i]]++;
if (i == (n - 1) / 2) {
std::cout << mp[a[i]] << "\n";
return ;
}
}
}

B. Maximum Sum

思路:

  • 只要找到一个最大子段和,然后一直向那个子段左右添加这个和即可,这样一定会使得结果最大

时间复杂度:\(O(n + 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
constexpr int P = 1E9 + 7;

void solve() {
int n, k;
std::cin >> n >> k;

std::vector<int> a(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
i64 x = 0, max = x;
for (int i = 0; i < n; i++) {
if (x > 0) {
x += a[i];
} else {
x = a[i];
}
if (x > max) {
max = x;
}
}
max = std::max(0LL, max);
i64 sum = std::accumulate(a.begin(), a.end(), 0LL);
i64 ans = 0;
for (int i = 0; i < k; i++) {
ans = (ans * 2 + max) % P;
}
std::cout << (ans + sum % P + P) % P << "\n";
}

C. Tree Cutting

思路:

  • 首先关注数据范围,\(K,N \le 10^5\) 那么本题一定需要一个 \(O(n)\) 或者 \(O(nlogn)\) 的算法,那么我们要求最大值 \(x\),可以发现要求最大的点集,我们可以二分,这个类似于求连通分量,可以用 \(dfs\) 来求出每一个点所属集合的点集大小,然后来二分 \(x\) 即可

时间复杂度:\(O(nlogn)\)

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
void solve() {
int n, k;
std::cin >> n >> k;

std::vector<std::vector<int>> adj(n);
for (int i = 1; i < n; i++) {
int u, v;
std::cin >> u >> v;
u--, v--;

adj[u].push_back(v);
adj[v].push_back(u);
}

int l = 1, r = n;
std::vector<int> vis(n), cnt(n);
while (l < r) {
int mid = l + r + 1 >> 1;
vis.assign(n, 0);
cnt.assign(n, 1);
int sum = 0;
auto dfs = [&](auto self, int u, int fa) -> void {
vis[u] = true;
for (auto x : adj[u]) {
if (x == fa || vis[x]) continue ;
self(self, x, u);
cnt[u] += cnt[x];
}
if (cnt[u] >= mid) {
sum += 1;
cnt[u] = 0;
}
};
dfs(dfs, 0, -1);
if (sum > k) {
l = mid;
} else {
r = mid - 1;
}
}
std::cout << l << "\n";
}