ABC463 解题报告
感觉这一场就是五道简单题 + 两道数学题。
为了自招保留下手感,没做 FG。
C
将所有人按照时间进行排序,统计高度的后缀最大值,每次通过二分找到所求后缀起点。
// Code by GENX.
// 2026-06-20
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 3e5 + 7;
int n, suf[N];
pair<int, int> a[N];
signed main(){
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for(int i = 1; i <= n; i ++){
cin >> a[i].second >> a[i].first;
}
sort(a + 1, a + n + 1);
for(int i = n; i >= 1; i --){
suf[i] = max(suf[i + 1], a[i].second);
}
int q; cin >> q;
while(q --){
int t; cin >> t;
int l = 0, r = n + 1;
while(l + 1 < r){
int mid = (l + r) >> 1;
if(a[mid].first <= t) l = mid;
else r = mid;
}
cout << suf[r] << "\n";
}
return 0;
}
D
依旧,二分答案。然后将所有区间按照右端点排序,就可以从前往后能选就选地贪心。
// Code by GENX.
// 2026-06-20
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 7;
vector<pair<int, int>> g[N];
int n, m, y, dis[N];
signed main(){
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> m >> y;
for(int i = 1; i <= m; i ++){
int u, v, w; cin >> u >> v >> w;
g[u].push_back({w << 1, v});
g[v].push_back({w << 1, u});
}
for(int i = 1; i <= n; i ++){
int x; cin >> x;
g[i].push_back({(x << 1) + y, 0});
g[0].push_back({(x << 1) + y, i});
}
memset(dis, 0x3f, sizeof dis);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
dis[1] = 0, q.push({dis[1], 1});
while(q.size()){
auto [d, u] = q.top(); q.pop();
if(d > dis[u]) continue;
for(auto [w, v]: g[u]){
if(dis[v] > dis[u] + w){
dis[v] = dis[u] + w;
q.push({dis[v], v});
}
}
}
for(int i = 2; i <= n; i ++){
cout << (dis[i] >> 1) << " ";
}
cout << "\n";
return 0;
}
E
这种传送门,单开一个点作为中转站就可以了。
具体地,我们在中转站 \(u\) 和每个节点 \(i\) 之间搭一条长度为 \(\frac{x_i + y}{2}\) 的边。
我选择所有边权翻倍,避免 double 的精度问题。
// Code by GENX.
// 2026-06-20
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 7;
vector<pair<int, int>> g[N];
int n, m, y, dis[N];
signed main(){
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> m >> y;
for(int i = 1; i <= m; i ++){
int u, v, w; cin >> u >> v >> w;
g[u].push_back({w << 1, v});
g[v].push_back({w << 1, u});
}
for(int i = 1; i <= n; i ++){
int x; cin >> x;
g[i].push_back({(x << 1) + y, 0});
g[0].push_back({(x << 1) + y, i});
}
memset(dis, 0x3f, sizeof dis);
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> q;
dis[1] = 0, q.push({dis[1], 1});
while(q.size()){
auto [d, u] = q.top(); q.pop();
if(d > dis[u]) continue;
for(auto [w, v]: g[u]){
if(dis[v] > dis[u] + w){
dis[v] = dis[u] + w;
q.push({dis[v], v});
}
}
}
for(int i = 2; i <= n; i ++){
cout << (dis[i] >> 1) << " ";
}
cout << "\n";
return 0;
}
F
注意到,在 \(w = \max{a}\)时,只有 \(a = w - 1\) 或 \(a = w\) 的人才有机会得到冠军。然后我们便把需要考虑的数限定在很小的范围内了。接下来就可以大力分类讨论了。
G
先把式子推一下,然后上莫队就好了,
感觉自己不是很擅长这类大力推式子的题。然后这个莫队 trick 之前也有出现过,是今年省选 Day1 晚上那一场的 F 题。
莫队可以看作一个平面内一组点的一种哈密顿路径(两点距离为曼哈顿距离)的构造方式。

浙公网安备 33010602011771号