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

推荐订阅源

F
Fortinet All Blogs
S
Secure Thoughts
月光博客
月光博客
美团技术团队
雷峰网
雷峰网
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
N
News and Events Feed by Topic
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Forbes - Security
Forbes - Security
W
WeLiveSecurity
P
Proofpoint News Feed
阮一峰的网络日志
阮一峰的网络日志
爱范儿
爱范儿
G
GRAHAM CLULEY
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
AI
AI
Last Week in AI
Last Week in AI
Google Online Security Blog
Google Online Security Blog
Schneier on Security
Schneier on Security
云风的 BLOG
云风的 BLOG
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Recent Announcements
Recent Announcements
Webroot Blog
Webroot Blog
T
Tor Project blog
Cisco Talos Blog
Cisco Talos Blog
N
News and Events Feed by Topic
罗磊的独立博客
The Register - Security
The Register - Security
Blog — PlanetScale
Blog — PlanetScale
T
Threat Research - Cisco Blogs
博客园 - 【当耐特】
Apple Machine Learning Research
Apple Machine Learning Research
人人都是产品经理
人人都是产品经理
T
The Exploit Database - CXSecurity.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
B
Blog
腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Engineering at Meta
Engineering at Meta
Latest news
Latest news
IT之家
IT之家
D
DataBreaches.Net
博客园 - 司徒正美
N
Netflix TechBlog - Medium
V
V2EX
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

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 912 (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) 关于 LRU map 的一些灵感 2023 杭州站 ICPC 现场赛 反复横跳的 Clang-Tidy(cert-dcl21-cpp) Codeforces Round 906 (Div. 2) 一段奇怪的 CPP 代码 Codeforces Round 905 (Div. 3) Codeforces Round 904 (Div. 2) Codeforces Round 903 (Div. 3) Educational Codeforces Round 156 (Rated for Div. 2) Codeforces Round 902 (Div. 2, based on COMPFEST 15 - Final Round) Codeforces Round 901 (Div. 2) Codeforces Round 900 (Div. 3) Codeforces Round 899 (Div. 2) Educational Codeforces Round#155 (Div. 2) Codeforces Round 898 (Div. 4) CodeTON Round 6 (Div. 2) Codeforces Round 897 (Div. 2) Codeforces Round 896 (Div. 2) Codeforces Round 887 (Div. 2) Codeforces Round 895 (Div. 3) 左值-右值-将亡值 blog.mauve.icu Pinely Round 2 (Div. 1 + Div. 2) Harbour.Space Scholarship Contest 2023-2024 (Div. 1 + Div. 2) Codeforces Round 894 (Div. 3) Codeforces Round 888 (Div. 3) Educational Codeforces Round#153 (Div. 2) Codeforces Round 893 (Div. 2) OTPAUTH,两步验证中的通用协议 Codeforces Round 892 (Div. 2) Codeforces Round 891 (Div. 3) Codeforces Round 890 (Div. 2) Educational Codeforces Round#152 (Div. 2) blog.mauve.icu Java Script 的 null 和 undefined 随想 记一次 SQL LEFT JOIN 没有得到预期结果的错误 Codeforces Round#789(Div. 2) GCC/G++ 预编译头性能优化 使用 Junit5 和 Mockito 实现 SpringBoot 的单元测试最优美的解决方案 centOS 防火墙 docker-compse 的问题 C++ 语言实现动态变化的线程池 Codeforces Round#744 (Div. 3) 计算机图形学 Windows 通过网络访问 WSL2 原生 JavaScript 实现图片裁剪 面试复习(计算机图形学) 面试复习(算法) Codeforces Round#706(Div. 2)-Let's Go Hiking 面试复习(Java) 面试复习(Git) 面试复习(Linux) 面试复习(数据库) 面试复习(计算机网络) 面试复习(操作系统) 面试复习(C++) Codeforces Round#699 (Div. 2) 清理 WSL2 的磁盘占用 Codeforces Round#697 (Div. 3) Windows 下的 NTFS 驱动器索引 BUG 计算机网络复习 记一次 Navicat 连接 MySQL 一直报认证错误(Access denied) 计算机网络实验复习 WSL1 使用 Docker 一直无法启动 我的ACM脚印 2020牛客暑期多校训练营(第三场)D-Points Construction Problem——构造 2020牛客暑期多校训练营(第三场)E-Two Matchings——复杂思维与简单dp 2020牛客暑期多校训练营(第二场)I-Interval——最大流转对偶图求最短路 Educational Codeforces Round 80 D. Minimax Problem——二分+二进制处理 Codeforces Round 606 E. Two Fairs——图论 Codeforces Round 612 (Div. 2) C. Garland——DP
Codeforces Round 916 (Div. 3)
Shiroha · 2023-12-21 · via Shiroha白羽的博客

这场本来是想在比赛的时候写的,可惜写到一半突然有公司的电话进来了,就只好先去处理点事情了

A. Problemsolving Log

大致题意

写出 A 题需要思考 1min,写出 B 题需要思考 2min,以此类推,给出一个人每分钟在思考的题,问最终有几道题能写出来

思路

简单题,统计一下每个字母出现次数就行了

AC code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void solve() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n;
cin >> n;
string str;
str.reserve(n);
cin >> str;
map<char, int> mp;
for (auto&c: str) mp[c]++;
int ans = 0;
for (char i = 'A'; i <= 'Z'; ++i)
if (mp[i] >= i - 'A' + 1) ans++;
cout << ans << endl;
}
}

B. Preparing for the Contest

大致题意

需要构造一个长度为 n 的序列,使得其满足所有相邻两个值中,存在恰好 k 个前者大于后者的对数

思路

也是简单题,想清楚怎么构造就行。比如我的思路是把最大的 k 个值按照递增序放在后面

AC code

1
2
3
4
5
6
7
8
9
10
11
12
void solve() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n, k;
cin >> n >> k;

for (int i = n - k; i > 0; --i) cout << i << " ";
for (int i = n - k + 1; i <= n; ++i) cout << i << " ";
cout << endl;
}
}

C. Quests

大致题意

有一堆问题,第一次写出来可以得到 $a_i$ 的分数,第二次及之后写出来可以得到 $b_i$ 的分数

每道题写出来的前提是前面的所有题至少都写出来一次

问最多写 $x$ 道题,最多可以得到多少分

思路

由于每道题必须要前面的所有题都写出来才能写,所以可以考虑枚举最终写到了哪道题,然后把剩下的所有写题的机会给那个 $b_i$ 最大的题即可

AC code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void solve() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n, k;
cin >> n >> k;
vector<int> a(n), b(n);
for (auto&i: a) cin >> i;
for (auto&i: b) cin >> i;

int ma = 0, ans = 0, suf = 0;
for (int i = 0; i < min(n, k); ++i) {
suf += a[i];
ma = max(ma, b[i]);
ans = max(ans, suf + (k - i - 1) * ma);
}
cout << ans << endl;
}
}

D. Three Activities

大致题意

有三种活动,且有 $n$ 天,每一天最多参加一个活动,每一个活动最多只能有一天参加。

每个活动每天都有其他伙伴一起来参加,数量都不相同。问应该挑哪三天去参加活动,能够使得一起参加的伙伴数量最多

思路

由于总共就只有三种活动,所以只需要挑选三天。对于每一个活动而言,他们只需要考虑参加伙伴最多的那三天即可

所以在每一个活动下单独排序参加的伙伴数量,选择每个活动下伙伴最多的三天,暴力找下答案即可

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
void solve() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n;
cin >> n;
vector<pair<int, int>> a(n), b(n), c(n);
for (auto&i: a) cin >> i.first;
for (auto&i: b) cin >> i.first;
for (auto&i: c) cin >> i.first;
for (int i = 0; i < n; ++i) a[i].second = i;
for (int i = 0; i < n; ++i) b[i].second = i;
for (int i = 0; i < n; ++i) c[i].second = i;

sort(a.begin(), a.end(), greater<>());
sort(b.begin(), b.end(), greater<>());
sort(c.begin(), c.end(), greater<>());

int ans = 0;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if (b[j].second == a[i].second) continue;
for (int k = 0; k < 3; ++k) {
if (c[k].second == a[i].second || c[k].second == b[j].second) continue;
ans = max(ans, a[i].first + b[j].first + c[k].first);
}
}
}
cout << ans << endl;
}
}

E2. Game with Marbles (Hard Version)

大致题意

直接看 Hard Version

Alice 和 Bob 做游戏,有 $n$ 种颜色的石头,每个人都有所有颜色的石头若干个

每轮,当前的选手需要选择一种颜色,然后当前选手丢掉一个这种颜色的石头,对方丢掉全部的

目标是让自己的石头数量之和尽可能多,问最后剩下多少个

思路

假如一种颜色的石头,Alice 有 $a$ 个,Bob 有 $b$ 个。如果是 Alice 选择,那么 Alice 会剩下 $a-1$ 个,差值是 $a-1$。如果是 Bob 选择,则是 $-(b-1)$

这样可以得到,不选择这个颜色的代价就是 $(a-1)-(-(b-1)) = (a+b-2)$,同时选择它的收益也是这个

按照代价排序,从最大的代价依次开始操作即可

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

void solve() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n;
cin >> n;
vector<int> a(n), b(n);
for (auto&i: a) cin >> i;
for (auto&i: b) cin >> i;
vector<pair<int, int>> d(n);
for (int i = 0; i < n; ++i) {
d[i].first = a[i] + b[i] - 2;
d[i].second = i;
}
sort(d.begin(), d.end(), greater<>());
for (int i = 0; i < n; ++i) {
if (i % 2) {
b[d[i].second]--;
a[d[i].second] = 0;
} else {
a[d[i].second]--;
b[d[i].second] = 0;
}
}
int ans = 0;
for (int i = 0; i < n; ++i) ans += a[i] - b[i];
cout << ans << endl;
}
}

F. Programming Competition

大致题意

一个公司,其上级或者间接的上级都是他老板,现在需要两两组队,但是有老板关系的不能组,问最多可以组几个队伍

思路

树上 dfs 搜索即可,每次传给当前节点,外面不属于他的员工的节点数量还有多少,有就用掉即可

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
void solve() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n;
cin >> n;
vector<int> p(n), d(n);
vector<vector<int>> tree(n);
for (int i = 1; i < n; ++i) {
int tmp;
cin >> tmp;
tree[tmp - 1].push_back(i);
}

function<int(int)> deep = [&](const int v) {
d[v] = 1;
for (auto& i: tree[v]) d[v] += deep(i);
return d[v];
};

int ans = 0;
function<void(int, int)> dfs = [&](const int v, int cnt) {
ans += cnt > 0;
if (cnt > 0) --cnt;

int sum = 0;
for (auto &i: tree[v]) sum += d[i];

for (auto &i: tree[v]) dfs(i, sum - d[i] + cnt);
};

// ReSharper disable once CppExpressionWithoutSideEffects
deep(0);
dfs(0, 0);
cout << ans / 2 << endl;
}
}

G2. Light Bulbs (Hard Version)

大致题意

这题还是挺有意思的

有一排灯,其中每种颜色的灯恰好有两个,可以选择开始的时候,点亮一部分灯,之后可以无限次进行如下操作

  • 点亮一盏灯,前提是和他相同颜色的另一盏灯已经点亮了
  • 选择一种颜色,其两盏灯都已经点亮了,将这两盏灯中间的所有灯点亮

问开始的时候最少选择几盏灯,就可以把所有灯都点亮。同时给出可以选择的数量

思路

首先,如果存在一个 $a$ 夹在两个 $b$ 之间,那么只需要点亮 $b$ 就可以点亮 $a$,我们可以进行建图来做

但是如果这样完整建图的成本会很高,所以得考虑优化一下
例如 $1,2,3,4,1,2,3,4$ 这种,就会变成一个全连接的图,而点数量有 $2 \times 10^5$,故不太行

由于这个图并不是传统的拓扑排序,而是只要上游任意一个点满足则满足(传统拓扑是上游均满足才满足)所以可以做反向路径压缩,即“别压缩”

例如上面的例子,仅实现与最后出现的那个区间进行连接,例如上图,则仅有 $1 \rightarrow 2 \rightarrow 3 \rightarrow 4 \rightarrow 1$,
容易的得到这样建图也是可以满足要求的,因为不是传统拓扑

那么只需要在创建完成图之后,将拓扑的首个节点序列拿出来即可,这些节点是必选。因为有两个相同颜色的灯,所以是 $2^x$ 种选择

接下来考虑成环的情况,我们只需要找出最初试图进入环的那个节点(最左边的节点,因为它必然可以连接到剩下所有的节点)
看剩下环内的节点是否能够反向到达它即可。可以反向建图来做。至于最初进入环的节点,可以用并查集

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
void solve() {
int _;
cin >> _;
for (int ts = 0; ts < _; ++ts) {
int n;
cin >> n;

struct node {
int v, n;
};
stack<int> st;
vector<node> edge, redge;
vector head(n + 1, -1), rhead(n + 1, -1), deg(n + 1, 0), fa(n + 1, 0), vis(n + 1, 0);
edge.reserve(n);
redge.reserve(n);
for (int i = 0; i < fa.size(); ++i) fa[i] = i;
function<int(int)> finds = [&](int x) { return fa[x] == x ? x : fa[x] = finds(fa[x]); };
function join = [&](const int x, const int y) {
const int rx = finds(x), ry = finds(y);
if (rx == ry) return;
fa[rx] = ry;
};

for (int i = 0; i < n * 2; ++i) {
int tmp;
cin >> tmp;
while (!st.empty() && vis[st.top()] == 2) st.pop();
if (!st.empty() && st.top() != tmp) {
join(tmp, st.top());
edge.push_back({tmp, head[st.top()]});
head[st.top()] = static_cast<int>(edge.size()) - 1;
deg[tmp]++;

redge.push_back({st.top(), rhead[tmp]});
rhead[tmp] = static_cast<int>(redge.size()) - 1;
}
st.push(tmp);
++vis[tmp];
}

queue<int> q;
for (int i = 1; i <= n; ++i) if (deg[i] == 0) q.push(i);
constexpr long long mod = 998244353;
const int res = static_cast<int>(q.size());

long long ans = 1;
for (int i = 0; i < q.size(); ++i) {
ans <<= 1;
ans %= mod;
}

while (!q.empty()) {
const int cur = q.front();
q.pop();
if (vis[cur] == 3) continue;
++vis[cur];
for (int i = head[cur]; ~i; i = edge[i].n) q.push(edge[i].v);
}

map<int, int> superCnt;
for (int i = 1; i <= n; ++i) if (vis[i] != 3 && finds(i) == i) q.push(i);

while (!q.empty()) {
const int cur = q.front();
q.pop();
if (vis[cur] == 3) continue;
++vis[cur];
superCnt[finds(cur)]++;
for (int i = rhead[cur]; ~i; i = redge[i].n)
q.push(redge[i].v);
}

for (auto [k, v]: superCnt) ans = ans * 2 * v % mod;

cout << (res + superCnt.size()) << ' ' << ans << endl;
}
}