VP Educational Codeforces Round 158 (Rated for Div. 2)
A. Line Trip
题意:你要从
显然油箱要支撑我们行驶完任意两个相邻点之间的路程,注意最后
点击查看代码
void solve() {
int n, x;
std::cin >> n >> x;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
int max = std::max(a[0], 2 * (x - a.back()));
for (int i = 1; i < n; ++ i) {
max = std::max(max, a[i] - a[i - 1]);
}
std::cout << max << "\n";
}
B. Chip and Ribbon
题意:n个数,每次你可以选择一段区间让这个区间的数都加
考虑一段升序的区间
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<i64> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
a.push_back(0);
i64 ans = 0, min = 0;
for (int i = 0; i < n; ++ i) {
if (a[i] > a[i + 1]) {
ans += a[i] - min;
min = a[i + 1];
}
}
std::cout << ans - 1 << "\n";
}
C. Add, Divide and Floor
题意:给你一个数组,每次选择一个数
因为所有数都是进行同样的操作,那么我们应该关注最大值变成目标值需要几次,一个可行方案是都变成
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
int min = *std::min_element(a.begin(), a.end());
int max = *std::max_element(a.begin(), a.end());
int ans = 0;
while (max != min) {
max = max + min >> 1;
++ ans;
}
std::cout << ans << "\n";
if (ans <= n) {
for (int i = 1; i <= ans; ++ i) {
std::cout << min << " \n"[i == ans];
}
}
}
D. Yet Another Monster Fight
题意:有
假设我们选择了
发现这两个区间一定是前缀或后缀,可以一个数组维护,但我赛时没想到,直接上了线段树。
点击查看代码
#define ls (u << 1)
#define rs (u << 1 | 1)
struct Node {
int l, r;
int max;
};
struct SegmentTree {
std::vector<Node> tr;
SegmentTree(int _n) {
tr.assign(_n << 2, {});
build(1, 1, _n);
}
void pushup(int u) {
tr[u].max = std::max(tr[ls].max, tr[rs].max);
}
void build(int u, int l, int r) {
tr[u] = {l, r};
int mid = l + r >> 1;
if (l == r) {
return;
}
build(ls, l, mid); build(rs, mid + 1, r);
}
void modify(int u, int p, int v) {
if (tr[u].l == tr[u].r) {
tr[u].max = v;
return;
}
int mid = tr[u].l + tr[u].r >> 1;
if (p <= mid) {
modify(ls, p, v);
} else {
modify(rs, p, v);
}
pushup(u);
}
int query(int u, int l, int r) {
if (l <= tr[u].l && tr[u].r <= r) {
return tr[u].max;
}
int mid = tr[u].l + tr[u].r >> 1;
if (r <= mid) {
return query(ls, l, r);
} else if (l > mid) {
return query(rs, l, r);
} else {
return std::max(query(ls, l, r), query(rs, l, r));
}
}
};
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
SegmentTree trl(n), trr(n);
for (int i = 0; i < n; ++ i) {
trl.modify(1, i + 1, a[i] + n - i - 1);
trr.modify(1, i + 1, a[i] + i);
}
int ans = 2e9;
for (int i = 1; i <= n; ++ i) {
if (i == 1) {
ans = std::min(ans, std::max(a[i - 1], trr.query(1, i + 1, n)));
} else if (i == n) {
ans = std::min(ans, std::max(a[i - 1], trl.query(1, 1, i - 1)));
} else {
ans = std::min(ans, std::max({a[i - 1], trr.query(1, i + 1, n), trl.query(1, 1, i - 1)}));
}
}
std::cout << ans << "\n";
}
E. Compressed Tree
题意:有一颗树,每个节点有权值,你可以每次选择一个叶子删掉,在你操作完之后,会删除所有有恰好两条边的点,问最后剩下的点权值和最大是多少。
考虑
那么求出来了
点击查看代码
void solve() {
int n;
std::cin >> n;
std::vector<i64> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
std::vector<std::vector<int> > adj(n);
for (int i = 1; i < n; ++ i) {
int u, v;
std::cin >> u >> v;
-- u, -- v;
adj[u].push_back(v);
adj[v].push_back(u);
}
std::vector<i64> f(n, 0);
i64 ans = 0;
auto dfs = [&](auto self, int u, int fa) -> void {
std::vector<i64> b;
f[u] = a[u];
ans = std::max(ans, a[u]);
for (auto & v : adj[u]) {
if (v == fa) {
continue;
}
self(self, v, u);
b.push_back(f[v]);
ans = std::max(ans, a[u] + f[v]);
}
std::sort(b.begin(), b.end(), std::greater<i64>());
if (b.size() == 1) {
f[u] = std::max(a[u], b[0]);
} else if (b.size() >= 2) {
i64 sum = b[0] + b[1];
f[u] = std::max({a[u], b[0], b[1], sum + a[u]});
ans = std::max(ans, sum);
for (int i = 2; i < b.size(); ++ i) {
sum += b[i];
f[u] = std::max(f[u], sum + a[u]);
ans = std::max(ans, sum + a[u]);
}
}
};
dfs(dfs, 0, -1);
std::cout << ans << "\n";
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现