惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
B
Blog
博客园_首页
C
Check Point Blog
Microsoft Security Blog
Microsoft Security Blog
MyScale Blog
MyScale Blog
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
B
Blog RSS Feed
M
MIT News - Artificial intelligence
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
WordPress大学
WordPress大学
宝玉的分享
宝玉的分享
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
量子位
V
V2EX
Y
Y Combinator Blog
Hugging Face - Blog
Hugging Face - Blog
Martin Fowler
Martin Fowler
Recent Announcements
Recent Announcements
I
InfoQ
博客园 - 【当耐特】

Shiroha白羽的博客

Golang 踩坑 —— interface 为参数的时候传 nil 指针 Codeforces Round 925 (Div. 3) Codeforces Round 924 (Div. 2) Codeforces Round 923 (Div. 3) Codeforces Round 922 (Div. 2) Codeforces Round 921 (Div. 2) Educational Codeforces Round 161 (Rated for Div. 2) Codeforces Round 920 (Div. 3) Codeforces Round 919 (Div. 2) Hello 2024 Good Bye 2023 Codeforces Round 918 (Div. 4) 个人备份的常用 macOS 清理命令 Codeforces Round 917 (Div. 2) Pinely Round 3 (Div. 1 + Div. 2) Educational Codeforces Round 160 (Rated for Div. 2) Codeforces Round 915 (Div. 2) Codeforces Round 914 (Div. 2) Codeforces Round 913 (Div. 3) Educational Codeforces Round 159 (Rated for Div. 2) Codeforces Round 911 (Div. 2) CodeTON Round 7 (Div. 1 + Div. 2, Rated, Prizes!) Educational Codeforces Round 158 (Rated for Div. 2) Codeforces Round 910 (Div. 2) Codeforces Round 909 (Div. 3) Codeforces Round 908 (Div. 2) Educational Codeforces Round 157 (Rated for Div. 2) C++自定义的字面量 Codeforces Round 907 (Div. 2) Codeforces Round 916 (Div. 3)
Codeforces Round 912 (Div. 2)
Shiroha · 2024-02-11 · via Shiroha白羽的博客

A. Halloumi Boxes

大致题意

有一个数组,每次允许选择其中一段长度不超过 $k$ 的字串进行翻转,问是否可能将其排序好

思路

最有用的翻转就是两个值,那就是冒泡了,所以要么本身有序,要么 $k \geq 2$ 就行了

AC code

1
2
3
4
5
6
7
8
9
10
11
12
13
void solve() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n, k;
cin >> n >> k;
vector<int> data(n);
for (auto& i: data) cin >> i;
bool sorted = true;
for (int i = 1; i < n; ++i) if (data[i] < data[i - 1]) sorted = false;
cout << (sorted || k >= 2 ? "YES" : "NO") << endl;
}
}

B. StORage room

大致题意

有一个矩阵,其中的每一项 $M_{i,j} = a_i | a_j$,问是否能得到原始数组的其中一种可能

思路

即然是 $M_{i,j} = a_i | a_j$,那么反过来可以得到 $a_i = M_{i,0} & M_{i,1} & M_{i,2} \dots$

这不一定是原始解,但是一定是正确的解。还原后再验证一下矩阵对不对就行了

AC code

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
void solve() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n;
cin >> n;
vector<vector<int>> data(n);
for (auto& i: data) i.resize(n);
for (auto& i: data) for (auto& j: i) cin >> j;
vector ans(n, -1);
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
if (j != i) ans[i] &= data[i][j];
bool check = true;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
if (i == j) continue;
if (data[i][j] != (ans[i] | ans[j])) check = false;
}
}
if (!check) cout << "NO" << endl;
else {
cout << "YES" << endl;
for (int i = 0; i < n; ++i) cout << (ans[i] == -1 ? 1 : ans[i]) << " \n"[i == n -1];
}
}
}

C. Theofanis’ Nightmare

大致题意

一个数组,其中有负值,将其拆成多个字串,然后按照原始顺序从左往右编号,从 1 开始编号

然后将每个字串内求和,乘上其的编号,最后再相加,问如何拆最大

思路

从最后一个值看,假如其为 $c$,那么如果其独立出去,和不独立出去,和前面的段合并,那么得到的差值就是 $c$,因为 $(n + 1) \times c - (n) \times c$

所以,如果 $c > 0$ 那么这样做是有意义的,反之则应该尽力避免拆

类推可以得到,如果当前值即之后的所有值加起来是 $< 0$,那么不要拆,反之则拆即可

AC code

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
#define int long long

void solve() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n;
cin >> n;
vector<int> data(n);
for (auto& i: data) cin >> i;
int sum = 0;
for (auto& i: data) sum += i;
int seg = 0, ans = 0;
for (auto& i: data) {
if (sum < 0) {
if (seg == 0) seg = 1;
ans += seg * i;
}
else {
++seg;
ans += seg * i;
}
sum -= i;
}
cout << ans << endl;
}
}

D1. Maximum And Queries (easy version)

大致题意

有一个数组,允许每次给其中一个值 $+1$,最多执行 $k$ 次,问最终得到的数组的每一项进行位与运算,问最大值可以是多少

思路

要从位运算上下思路

如果一个值的某个位不是 1,那么如果通过 $+1$ 的方式把它变成 1,带来的后果就是更低位置的都会归零

所以我们需要从高位开始枚举位置,假设把这个位置大家都变成 1,那么就可以带来结果上的增长,但是会需要消耗一定的 $k$

注意一旦消耗过 $k$,那么再试图对这个值进行累加的时候,要把低位都认为是 0

AC code

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
#define int long long

void solve() {
int n, q;
cin >> n >> q;
vector<int> data(n);
for (auto& i: data) cin >> i;
while (q--) {
int k, ans = 0;
cin >> k;
vector flag(n, false);
for (int i = 62; i >= 0; --i) {
// try this bit
int cost = 0;
const int p = 1LL << i;
vector tmp(n, false);
for (int j = 0; j < n; ++j) {
if (flag[j]) cost += p;
else {
if (data[j] & p) continue;
cost += p - data[j] % p;
tmp[j] = true;
}

if (cost < 0) {
cost = k + 1;
break;
}
}
if (k >= cost) {
k -= cost;
ans += p;
for (int j = 0; j < n; ++j) flag[j] = tmp[j] | flag[j];
}
}
cout << ans << endl;
}
}

E. Geo Game

大致题意

有两个人博弈,二维屏幕上有一些点,其中一个固定为起始点,两个人轮流指定下一个点,不可以是之前选中的点,直到所有点都被走到

然后求算路径的欧几里得距离的平方和,问能否保证是偶数或者是奇数

思路

仔细思考就会发现很像是一笔画问题

如果某个点与开始点的欧几里得距离是奇数,我将其归为一类 A,另外的点为另外一类 B。那么显然,同一个类内的点相互走并不会变化结果的奇偶性。
但是不同类的路径就会变化奇偶性。非常巧的是,因为每个点都会被进入一次和出去一次,
所以理论如果要回到开始点,那么最终一定是偶数,因为一旦进入 A 类,就一定要回去 B 类,即每个 A 类的点会产生两条路径,也就是最终没有变化奇偶性

那么我们可以得到,如果 A 类点作为最后一个点,那么路径就是奇数的,否则就是偶数,然后再根据博弈再去模拟即可

AC code

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
void solve() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n, sx, sy;
cin >> n >> sx >> sy;
set<int> data[2];
for (int i = 0; i < n; ++i) {
int u, v;
cin >> u >> v;
const int cost = abs(u - sx) + abs(v - sy);
data[cost % 2].insert(i + 1);
}

if (data[0].size() >= data[1].size()) {
// chose first
cout << "First" << endl;
for (int i = 0; i < n; ++i) {
if (data[1].empty()) {
auto iter = data[0].begin();
cout << *iter << endl;
data[0].erase(iter);
} else {
auto iter = data[1].begin();
cout << *iter << endl;
data[1].erase(iter);
}

++i;
if (i < n) {
// read
int tmp;
cin >> tmp;
data[0].erase(tmp);
data[1].erase(tmp);
}
}
} else {
// chose second
cout << "Second" << endl;
for (int i = 0; i < n; ++i) {
int tmp;
cin >> tmp;
data[0].erase(tmp);
data[1].erase(tmp);
++i;

if (i < n) {
if (data[0].empty()) {
auto iter = data[1].begin();
cout << *iter << endl;
data[1].erase(iter);
} else {
auto iter = data[0].begin();
cout << *iter << endl;
data[0].erase(iter);
}
}
}
}
}
}