AtCoder Beginner Contest 359
A - Count Takahashi
水一篇
代码实现
#include <bits/stdc++.h>
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
int main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
int n ;
std::cin >> n;
int ans = 0;
for (int i = 0; i < n; ++i) {
std::string s;
std::cin >> s;
ans += s == "Takahashi";
}
std::cout << ans << "\n";
}
B - Couples
代码实现
#include <bits/stdc++.h>
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
int main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
int n ;
std::cin >> n;
n *= 2;
std::vector<int> a(n);
for (int i = 0; i < n; ++i) {
std::cin >> a[i];
}
int ans = 0;
for (int i = 1; i < n - 1; ++i) {
if (a[i - 1] == a[i + 1]) {
ans += 1;
}
}
std::cout << ans << "\n";
}
C - Tile Distance 2
代码实现
#include <bits/stdc++.h>
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
int main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
#define int long long
int sx, sy, tx, ty;
std::cin >> sx >> sy >> tx >> ty;
int dy = std::abs(sy - ty);
if (sx > tx) {
sx -= (sx + sy) % 2, tx += !((tx + ty) % 2);
tx += dy;
std::cout << dy + std::max(0LL, (sx - tx + 1) / 2) << '\n';
} else if (sx < tx) {
sx += !((sx + sy) % 2), tx -= (tx + ty) % 2;
sx += dy;
std::cout << dy + std::max(0LL, (tx - sx + 1) / 2) << '\n';
} else {
std::cout << std::abs(ty - sy) << '\n';
}
}
E - Water Tank
代码实现
#include <bits/stdc++.h>
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
int main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
#define int long long
int n ;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++i) {
std::cin >> a[i];
}
std::vector<int> stk;
std::vector<int> ans(n);
for (int i = 0; i < n; ++i) {
while (size(stk) && a[stk.back()] < a[i]) {
stk.pop_back();
}
if (empty(stk)) {
ans[i] = (i + 1) * a[i] + 1;
} else {
ans[i] = ans[stk.back()] + (i - stk.back()) * a[i];
}
stk.emplace_back(i);
}
for (int i = 0; i < n; ++i) {
std::cout << ans[i] << " \n"[i == n - 1];
}
}
F - Tree Degree Optimization
分析
贪心。在确保每个点都有入度的情况下,每次添加\((d^2-(d-1)^2)*a_i\)即可。
代码实现
#include <bits/stdc++.h>
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
int main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
#define int long long
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++i) {
std::cin >> a[i];
}
int ans = 0;
std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, std::greater<>> q;
for (int i = 0; i < n; ++i) {
ans += a[i];
q.emplace(3LL * a[i], 2);
}
for (int i = 1; i < n - 1; ++i) {
auto [w, num] = q.top();
q.pop();
ans += w;
q.emplace(w / (2 * num - 1) * (2 * num + 1), num + 1);
}
std::cout << ans << '\n';
}
G - Sum of Tree Distance
分析
按照点的种类建虚树统计代价即可。
代码实现
#include <bits/stdc++.h>
#ifdef LOCAL
#include "algo/debug.h"
#else
#define debug(...) 42
#endif
#define int long long
using Edge = int;
struct HLD {
int n, times = 0;
std::vector<int> siz, top, dep, fa, in, out, seq;
std::vector<std::vector<Edge>> adj;
HLD(const auto &adj, int root = 1) : n((int)adj.size() - 1), adj(adj) {
siz.resize(n + 1), top.resize(n + 1), dep.resize(n + 1), in.resize(n + 1), out.resize(n + 1), seq.resize(n + 1), fa.resize(n + 1);
dep[root] = 1, top[root] = root;
dfsSiz(root), dfsHld(root);
}
void dfsSiz(int u) {
if (fa[u] != 0) {
adj[u].erase(std::find(adj[u].begin(), adj[u].end(), fa[u]));
}
siz[u] = 1;
for (auto &v : adj[u]) {
fa[v] = u;
dep[v] = dep[u] + 1;
dfsSiz(v);
siz[u] += siz[v];
if (siz[v] > siz[adj[u][0]]) {
std::swap(v, adj[u][0]);
}
}
}
void dfsHld(int u) {
in[u] = ++times;
seq[in[u]] = u;
for (auto v : adj[u]) {
top[v] = v == adj[u][0] ? top[u] : v;
dfsHld(v);
}
out[u] = times;
}
int lca(int u, int v) {
while (top[u] != top[v]) {
dep[top[u]] > dep[top[v]] ? u = fa[top[u]] : v = fa[top[v]];
}
return dep[u] < dep[v] ? u : v;
}
int rootedLca(int a, int b, int c) { return lca(a, b) ^ lca(b, c) ^ lca(a, c); }
int dist(int u, int v) { return dep[u] + dep[v] - 2 * dep[(lca(u, v))]; }
bool inSubtree(int u, int v) { return in[v] <= in[u] && in[u] <= out[v]; }
int jump(int u, int k) {
if (dep[u] < k) return -1;
int d = dep[u] - k;
while (dep[top[u]] - d && u) u = fa[top[u]];
return seq[in[u] - dep[u] + d];
}
template<typename Q>
void modifyPath(int u, int v, const Q &q, bool edge = false) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) std::swap(u, v);
q(in[top[u]], in[u]);
u = fa[top[u]];
}
if (dep[u] > dep[v]) std::swap(u, v);
q(in[u] + edge, in[v]);
}
template<typename Q>
void modifySubtree(int u, const Q &q) { q(in[u], out[u]); }
template<typename T, typename Q>
T queryPath(int u, int v, const Q &q, bool edge = false) {
T ret = T();
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) std::swap(u, v);
ret = q(in[top[u]], in[u]) + ret;
u = fa[top[u]];
}
if (dep[u] > dep[v]) std::swap(u, v);
return q(in[u] + edge, in[v]) + ret;
}
template<typename T, typename Q>
T querySubtree(int u, const Q &q) { return q(in[u], out[u]); }
template<typename T, typename Q, typename F>
T queryPathNoncommutative(int u, int v, const Q &q, const F &f, bool edge = false) {
T left = T(), right = T();
while(top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) std::swap(u, v), std::swap(left, right);
left = q(in[top[u]], in[u]) + left;
u = fa[top[u]];
}
if (dep[u] > dep[v]) std::swap(u, v), std::swap(left, right);
return f(left, q(in[u] + edge, in[v]) + right);
}
template<typename T, typename Q>
T queryPathDirection(int u, int v, const Q &q, bool edge = false) {
T left = T(), right = T();
while(top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) {
right = q(in[top[v]], in[v]) + right;
v = fa[top[v]];
} else {
left = q(in[top[u]], in[u]) + left;
u = fa[top[u]];
}
}
if (dep[u] > dep[v]) {
left = q(in[v], in[u]) + left;
} else {
right = q(in[u], in[v]) + right;
}
std::swap(left.lmx, left.rmx);
return left + right;
}
std::pair<std::unordered_map<int, std::vector<int>>, int> virtualTree(std::vector<int> v) {
auto cmp = [&](int a, int b) { return in[a] < in[b]; };
std::sort(v.begin(), v.end(), cmp);
v.erase(std::unique(v.begin(), v.end()), v.end());
const int k = (int)size(v);
for (int i = 0; i + 1 < k; ++i) {
v.push_back(lca(v[i], v[i + 1]));
}
std::sort(v.begin(), v.end(), cmp);
v.erase(std::unique(v.begin(), v.end()), v.end());
std::unordered_map<int, std::vector<int>> res;
std::vector<int> stk;
for (auto x : v) {
while (!stk.empty() && out[stk.back()] < in[x]) {
stk.pop_back();
}
if (!stk.empty()) {
res[stk.back()].push_back(x);
}
stk.push_back(x);
}
return {res, v[0]};
}
std::pair<std::vector<int>, std::vector<std::pair<int, int>>> compress(std::vector<int> v) {
auto cmp = [&](int a, int b) { return in[a] < in[b]; };
std::sort(v.begin(), v.end(), cmp);
v.erase(std::unique(v.begin(), v.end()), v.end());
const int k = (int)size(v);
for (int i = 0; i + 1 < k; ++i) {
v.push_back(lca(v[i], v[i + 1]));
}
std::sort(v.begin(), v.end(), cmp);
v.erase(std::unique(v.begin(), v.end()), v.end());
std::vector<std::pair<int, int> > edges;
std::vector<int> stk;
for (auto x : v) {
while (!stk.empty() && out[stk.back()] < in[x]) {
stk.pop_back();
}
if (!stk.empty()) {
edges.push_back({stk.back(), x});
}
stk.push_back(x);
}
return {v, edges};
}
};
signed main() {
std::cin.tie(nullptr)->sync_with_stdio(false);
int n;
std::cin >> n;
std::vector<std::vector<int>> g(n + 1);
for (int i = 0; i < n - 1; ++i) {
int u, v;
std::cin >> u >> v;
g[u].emplace_back(v);
g[v].emplace_back(u);
}
std::vector<int> a(n);
for (int i = 0; i < n; ++i) {
std::cin >> a[i];
}
HLD hld(g);
std::vector<std::vector<int>> vs(n + 1);
for (int i = 0; i < n; ++i) {
vs[a[i]].emplace_back(i + 1);
}
int ans = 0;
for (int i = 1; i <= n; ++i) if (size(vs[i]) > 1) {
auto [g, root] = hld.virtualTree(vs[i]);
debug(i);
auto dfs = [&](auto &&self, int u)->int {
int sum = a[u - 1] == i;
for (auto v : g[u]) {
int siz = self(self, v);
ans += hld.dist(u, v) * siz * ((int)size(vs[i]) - siz);
sum += siz;
}
debug(u, sum);
return sum;
};
dfs(dfs, root);
}
std::cout << ans << '\n';
}