A. Insert
模拟
代码实现
n, k, x = map(int, input().split())
a = list(map(int, input().split()))
a.insert(k, x)
print(*a)
B. Intersection of Cuboids
模拟
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
struct Point {
int x, y, z;
};
Point input() {
Point p;
cin >> p.x >> p.y >> p.z;
return p;
}
bool solve() {
Point l1 = input();
Point r1 = input();
Point l2 = input();
Point r2 = input();
rep(i, 2) {
if (r1.x <= l2.x) return false;
if (r1.y <= l2.y) return false;
if (r1.z <= l2.z) return false;
swap(l1, l2);
swap(r1, r2);
}
return true;
}
int main() {
if (solve()) puts("Yes");
else puts("No");
return 0;
}
C. Make Them Narrow
对序列 \(A\) 做一遍升序排序,然后遍历所有大小为 \(n-k\) 的窗口即可
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> a(n);
rep(i, n) cin >> a[i];
sort(a.begin(), a.end());
int ans = 1e9;
rep(l, k+1) {
int r = l+(n-k)-1;
int now = a[r] - a[l];
ans = min(ans, now);
}
cout << ans << '\n';
return 0;
}
D. Go Stone Puzzle
BFS
将当前所有格子的石头的摆放情况作为状态,然后跑最短路即可
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
int main() {
int n;
string s, t;
cin >> n >> s >> t;
s += "..";
t += "..";
map<string, int> dist;
queue<string> q;
dist[s] = 0; q.push(s);
while (q.size()) {
string s = q.front(); q.pop();
int j = 0;
while (s[j] != '.') ++j;
rep(i, n+1) {
if (s[i] == '.' or s[i+1] == '.') continue;
string ns = s;
swap(ns[i], ns[j]);
swap(ns[i+1], ns[j+1]);
if (dist.count(ns)) continue;
dist[ns] = dist[s]+1;
q.push(ns);
}
}
if (dist.count(t)) cout << dist[t] << '\n';
else cout << "-1\n";
return 0;
}
E. Tree and Hamilton Path 2
考虑最后会返回到起点的情况,就是选取一点出发跑一遍dfs,树上每条边都会遍历2次,所以答案为 \(2\sum C_i\)
对于原题,我们可以考虑找到树上的一条直径,从直径上的点走到不在直径上的点再返回到直径上每条边会遍历2次,而在直径上的边只会遍历一次,所以答案就是用上面那种情况的费用减去直径的边数即可
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
struct Edge {
int to, cost;
Edge(int to, int cost): to(to), cost(cost) {}
};
int main() {
int n;
cin >> n;
ll ans = 0;
vector<vector<Edge>> g(n);
rep(i, n-1) {
int a, b, c;
cin >> a >> b >> c;
--a; --b;
g[a].emplace_back(b, c);
g[b].emplace_back(a, c);
ans += c*2;
}
auto dfs = [&](auto& f, int v, ll d=0, int p=-1) -> pair<ll, int> {
auto res = make_pair(d, v);
for (auto e : g[v]) {
if (e.to == p) continue;
res = max(res, f(f, e.to, d+e.cost, v));
}
return res;
};
int a = dfs(dfs, 0).second;
ll diameter = dfs(dfs, a).first;
ans -= diameter;
cout << ans << '\n';
return 0;
}
F. x = a^b
可以先求出满足 \(x^b \leqslant n\) 的 \(x=a\) 的个数,只需二分即可
然后注意到 \(64 = 2^6 = 4^3 = 8^2\),可以发现 \(6\) 是 \(3\) 和 \(2\) 的倍数,所以可以考虑对指数 \(b\) 进行容斥
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
ll calc(int b, ll n) {
ll ac = 0, wa = n+1;
// ac^b <= n
while (ac+1 < wa) {
ll wj = (ac+wa)/2;
auto ok = [&]{
ll x = 1;
rep(i, b) {
if (n/x < wj) return false;
x *= wj;
}
return x <= n;
}();
(ok ? ac : wa) = wj;
}
return ac-1;
}
int main() {
ll n;
cin >> n;
const int M = 60;
vector<ll> f(M);
ll ans = 1;
for (int b = M-1; b >= 2; --b) {
f[b] = calc(b, n);
for (int i = b*2; i < M; i += b) f[b] -= f[i];
ans += f[b];
}
cout << ans << '\n';
return 0;
}
G. Go Territory
可以考虑对同行连续的空格构成的连通块做缩点,然后用并查集对相邻两行中上下相邻的点做合并,再判断遍历每个点,判断当前点是否和以坐标 \((-1, -1)\) 所在行的连通块的点连通即可
代码实现
#include <bits/stdc++.h>
#if __has_include(<atcoder/all>)
#include <atcoder/all>
using namespace atcoder;
#endif
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
struct Range {
int l, r, id;
Range(int l, int r, int id): l(l), r(r), id(id) {}
};
int main() {
int n;
cin >> n;
const int M = 200005;
vector<vector<int>> xs(M);
rep(i, n) {
int x, y;
cin >> x >> y;
x++; y ++;
xs[y].push_back(x);
}
vector<vector<Range>> rngs(M);
int m = 0;
rep(y, M) {
auto& nxs = xs[y];
ranges::sort(nxs);
int l = 0;
for (int x : nxs) {
if (l < x) {
rngs[y].emplace_back(l, x, m++);
}
l = x+1;
}
rngs[y].emplace_back(l, M, m++);
}
dsu uf(m);
rep(y, M-1) {
auto& rngs1 = rngs[y];
auto& rngs2 = rngs[y+1];
vector<int> xs;
for (auto rng : rngs1) xs.push_back(rng.l);
for (auto rng : rngs2) xs.push_back(rng.l);
ranges::sort(xs);
int i1 = 0, i2 = 0;
for (int x : xs) {
while (rngs1[i1].r <= x) i1++;
while (rngs2[i2].r <= x) i2++;
if (rngs1[i1].l > x) continue;
if (rngs2[i2].l > x) continue;
uf.merge(rngs1[i1].id, rngs2[i2].id);
}
}
ll ans = 0;
rep(y, M) {
for (auto rng : rngs[y]) {
if (uf.same(0, rng.id)) continue;
ans += rng.r - rng.l;
}
}
cout << ans << '\n';
return 0;
}