Loading

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 题。

莫队可以看作一个平面内一组点的一种哈密顿路径(两点距离为曼哈顿距离)的构造方式。

posted @ 2026-06-20 22:25  Trent900  阅读(22)  评论(0)    收藏  举报