Educational Codeforces Round 36 (Rated for Div. 2)
1.Codeforces Round 598 (Div.3 )2.Codeforces Round 595 (Div. 3)3.Codeforces Round 699 (Div. 2)4.Codeforces Round 903 (Div. 3)5.CodeCraft-21 and Codeforces Round 711 (Div. 2)
6.Educational Codeforces Round 36 (Rated for Div. 2)
Educational Codeforces Round 36 (Rated for Div. 2)
A
直接枚举即可
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, k;
std::cin >> n >> k;
int ans = 1e9;
for (int i = 1; i <= n; i++) {
int x;
std::cin >> x;
if (k % x == 0) {
ans = std::min(ans, k / x);
}
}
std::cout << ans << '\n';
return 0;
}
B
分类讨论:
注意
#include <bits/stdc++.h>
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, pos, l, r;
std::cin >> n >> pos >> l >> r;
if (l == 1 && r == n) {
std::cout << 0 << '\n';
return 0;
}
if (l == 1) {
std::cout << std::abs(r - pos) + 1 << '\n';
} else if (r == n) {
std::cout << std::abs(l - pos) + 1 << '\n';
} else {
std::cout << r - l + std::min(std::abs(l - pos), std::abs(r - pos)) + 2 << '\n';
}
return 0;
}
C
首先特判如果
否则就是两个位数一样,我们从高位到地位一次贪心,每次尝试填某个数
D
直接枚举断哪条边,复杂度显然是
那么我们必然得删在某一个环上面。
由于
#include <bits/stdc++.h>
const int N = 510;
std::vector<int> g[N];
int st[N], fa[N];
std::vector<int> cir;
bool vis[N][N];
bool dfs(int u) {
st[u] = 1;
for (auto v : g[u]) {
if (!st[v]) {
fa[v] = u;
if (dfs(v)) return true;
} else if (st[v] == 1) {
int x = u;
while (true) {
cir.push_back(x);
if (x == v) break;
x = fa[x];
}
return true;
}
}
st[u] = 2;
return false;
}
bool DFS(int u) {
st[u] = 1;
for (auto v : g[u]) {
if (vis[u][v]) continue;
if (!st[v]) {
if (DFS(v)) return true;
} else if (st[v] == 1) {
return true;
}
}
st[u] = 2;
return false;
}
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, m;
std::cin >> n >> m;
while (m--) {
int u, v;
std::cin >> u >> v;
g[u].push_back(v);
}
bool ok = false;
for (int i = 1; i <= n; i++) {
if (!st[i] && dfs(i)) {
ok = true;
break;
}
}
if (!ok) {
std::cout << "YES\n";
return 0;
}
//枚举断掉环上的任意一条边
for (int i = 0; i < cir.size(); i++) {
vis[cir[(i + 1) % (int)cir.size()]][cir[i]] = true;
memset(st, 0, sizeof st);
bool ok = true;
for (int j = 1; j <= n; j++) {
if (!st[j] && DFS(j)) {
ok = false;
break;
}
}
if (ok) {
std::cout << "YES\n";
return 0;
}
vis[cir[(i + 1) % (int)cir.size()]][cir[i]] = false;
}
std::cout << "NO\n";
return 0;
}
E
经典的线段树题,我们把询问离散化,注意端点弄成
然后就变成一个区间推平,区间求和的板子题:
#include <bits/stdc++.h>
const int N = 6e5 + 10;
std::vector<int> v;
int sum[4 * N], tag[4 * N], len[4 * N];
void build(int u, int l, int r) {
tag[u] = -1;
if (l == r) {
sum[u] = len[u] = v[l] - v[l - 1];
return;
}
int mid = (l + r) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
sum[u] = sum[u << 1] + sum[u << 1 | 1];
len[u] = len[u << 1] + len[u << 1 | 1];
}
void push(int u) {
if (tag[u] != -1) {
sum[u << 1] = len[u << 1] * tag[u];
sum[u << 1 | 1] = len[u << 1 | 1] * tag[u];
tag[u << 1] = tag[u];
tag[u << 1 | 1] = tag[u];
tag[u] = -1;
}
}
void modify(int u, int l, int r, int ql, int qr, int t) {
if (l >= ql && r <= qr) {
sum[u] = len[u] * t;
tag[u] = t;
return;
}
push(u);
int mid = (l + r) >> 1;
if (ql <= mid) modify(u << 1, l, mid, ql, qr, t);
if (qr > mid) modify(u << 1 | 1, mid + 1, r, ql, qr, t);
sum[u] = sum[u << 1] + sum[u << 1 | 1];
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n, q;
std::cin >> n >> q;
v.push_back(1), v.push_back(n + 1);
std::vector<std::array<int, 3>> qry(q);
for (int i = 0; i < q; i++) {
auto& [k, l, r] = qry[i];
std::cin >> l >> r >> k;
if (k == 1) k = 0;
else k = 1;
v.push_back(l), v.push_back(++r);
}
std::sort(v.begin(), v.end());
v.erase(std::unique(v.begin(), v.end()), v.end());
int m = (int)v.size() - 1;
build(1, 1, m);
for (int i = 0; i < q; i++) {
auto [k, l, r] = qry[i];
l = std::lower_bound(v.begin(), v.end(), l) - v.begin() + 1;
r = std::lower_bound(v.begin(), v.end(), r) - v.begin();
modify(1, 1, m, l, r, k);
std::cout << sum[1] << '\n';
}
return 0;
}
F
经典的 trick:
- 首先最大值和最小值可以分开求和
- 对于这类求两两路径的东西,且和权值大小有关,我们可以直接排序+并查集即可。
按点权从小到大,每次拿出点
#include <bits/stdc++.h>
typedef long long i64;
int main(){
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int n;
std::cin >> n;
std::vector<int> a(n + 1);
std::vector<int> q(n + 1);
for (int i = 1; i <= n; i++) {
q[i] = i;
}
std::vector<std::vector<int>> g(n + 1);
std::vector<int> p(n + 1), sz(n + 1, 0);
for (int i = 1; i <= n; i++) {
p[i] = i, sz[i] = 1;
}
std::function<int(int)> find = [&](int x) {
return x == p[x] ? x : p[x] = find(p[x]);
};
for (int i = 1; i <= n; i++) {
std::cin >> a[i];
}
for (int i = 1; i < n; i++) {
int u, v;
std::cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
std::sort(q.begin() + 1, q.end(), [&](int x, int y) {
return a[x] < a[y];
});
std::vector<bool> vis(n + 1, false);
i64 ans = 0;
for (int i = 1; i <= n; i++) {
int u = q[i];
vis[u] = true;
for (auto v : g[u]) {
if (!vis[find(v)]) continue;
ans += 1LL * sz[find(v)] * sz[find(u)] * a[u];
sz[find(u)] += sz[find(v)];
p[find(v)] = find(u);
}
}
for (int i = 1; i <= n; i++) {
p[i] = i, sz[i] = 1;
vis[i] = false;
}
for (int i = n; i >= 1; i--) {
int u = q[i];
vis[u] = true;
for (auto v : g[u]) {
if (!vis[find(v)]) continue;
ans -= 1LL * sz[find(v)] * sz[find(u)] * a[u];
sz[find(u)] += sz[find(v)];
p[find(v)] = find(u);
}
}
std::cout << ans << '\n';
return 0;
}
合集:
日常训练 (CF)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】