Codeforces Round 958 (Div.2)

7月11日 Codeforces 实战记录。(1505 -> 1531)

AC数3/6
比赛跳转:Codeforces Round 958 (Div. 2)

题解

A. Split the Multiset

即求 (n - 1) / (k - 1) 的上取整。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include<bits/stdc++.h>
#define int long long
using namespace std;

inline int read(){
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}

void solve(){
int n = read(), k = read();
cout << (n - 1 + k - 2) / (k - 1) << '\n';
}

signed main(){
int t = read();
while(t--) solve();
return 0;
}

B. Make Majority

考虑结束状态:1 的个数严格大于 0 的个数。
所以只考虑 减少1的个数 严格少于 减少0的个数 的操作。
将整块的 0 全部合并为一个 0,再考虑0,1的个数即可。

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
#include<bits/stdc++.h>
#define int long long
using namespace std;

inline int read(){
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}

void solve(){
int n = read();
string s; cin >> s;
int cnt0 = 0, cnt1 = 0;

for(int i = 0; i < n;){
if(s[i] == '1') {
cnt1 ++;
i++;
}
else{
cnt0++;
while(s[i] == '0' && i < n){
i++;
}
}
}
// cout << cnt0 << ' ' << cnt1 << '\n';
if(cnt1 > cnt0) cout << "Yes" << '\n';
else cout << "No" << '\n';
}

signed main(){
int t = read();
while(t--) solve();
return 0;
}

C. Increasing Sequence with Fixed OR

构造题,注意:
1.移位时记得用 1ll (犯错的人被卡了18min)
2.对 long long 类型 要用 __builtin_popcountll() 函数 (犯错的人被卡了45min)

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
#include<bits/stdc++.h>
#define int long long
using namespace std;

inline int read() {
int x = 0, f = 1; char ch = getchar();
while (ch < '0' || ch > '9') { if (ch == '-') f = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}

void solve() {
int n = read();
int k = __builtin_popcountll(n);

if(k == 1){
cout << 1 << '\n';
cout << n << '\n';
return;
}

cout << k + 1 << '\n';
for(int i = 60; i >= 0; i--){
if(n >> i & 1){
cout << (n ^ (1ll << i)) << ' ';
}
}
cout << n << '\n';
}

signed main() {
int t = read();
while (t--) solve();
return 0;
}

D. The Omnipotent Monster Killer

树形dp,状态转移方程:
$$
dp[u][i] = a[u] * i + \sum_{v\in g[u]}\min_{1\leq j\leq m,\ i!= j} dp[v][j]
$$

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
55
56
57
58
59
60
61
62
#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;

inline int read(){
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') f = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = x * 10 + ch - 48; ch = getchar(); }
return x * f;
}

const int N = 3e5 + 10, M = 20;
vector<int>g[N];
int a[N], dp[N][M];

void dfs(int u, int fa){
for(int i = 1; i < M; i++){
dp[u][i] = a[u] * i;
}
for(auto &v : g[u]){
if(v == fa) continue;
dfs(v, u);

int pos = -1, minn = 1e18;
for(int j = 1; j < M; j++){
if(dp[v][j] < minn){
minn = dp[v][j];
pos = j;
}
}

int last = 1e18;
for(int j = 1; j < M; j++){
if(j == pos) continue;
last = min(last, dp[v][j]);
}

for(int i = 1; i < M; i++){
if(i == pos) dp[u][i] += last;
else dp[u][i] += minn;
}

}
}

void solve(){
int n = read();
for(int i = 1; i <= n; i++) a[i] = read(), g[i].clear();
for(int i = 1; i < n; i++){
int x = read(), y = read();
g[x].emplace_back(y);
g[y].emplace_back(x);
}
dfs(1, 0);
cout << *min_element(dp[1] + 1, dp[1] + M) << '\n';
}

signed main(){
int t = read();
while(t--) solve();
return 0;
}