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';
}
posted @ 2024-06-23 00:37  sleeeeeping  阅读(50)  评论(0编辑  收藏  举报