競プロ精進日記 #61
精進や復習で解いた問題を載せていきます。
yukicoder
No.723 2つの数の和
map などで各要素数をカウントしておきます。
答えが int の範囲に収まらないことがあるので注意が必要です。
提出したソースコードNo.1110 好きな歌
ソートして2分探索でもとめていきます。
提出したソースコードNo.554 recurrence formula
n の制約が小さいので愚直にシミュレーションをすれば間に合います。
提出したソースコード
競プロ精進日記 #60
精進や復習で解いた問題を載せていきます。
AtCoder
ABC172 C - Tsundoku
累積和 + 二分探索の典型です。
提出したソースコードAising2020 A - Number of Multiples
シミュレーションを行いました。
提出したソースコードAising2020 B - An Odd Problem
ループを回して確認するだけです。
提出したソースコードAising2020 C - XYZ Triplets
式の条件より、x, y, z についてそれぞれ最大でも まで見れば良いことがわかります。
制約的に全探索で十分間に合うので終わりです。
提出したソースコード
競プロ精進日記 #59
精進や復習で解いた問題を載せていきます。
AtCoder
ABC173 A - Payment
支払う金額をシミュレーションして求めました。
提出したソースコードABC173 B - Judge Status Summary
map で管理しました。
提出したソースコードABC173 C - H and V
行と列に対して bit 全探索を用いて計算します。
提出したソースコードABC173 D - Chat in a Circle
大きい人から順に登場させます。
要素内最大の値は 1 回、それ以外は最大でも 2 回心地良さに寄与できるため、n - 1 回で得られる心地良さの最大値を求められます。
提出したソースコード
競プロ精進日記 #58
精進や復習で解いた問題を載せていきます。
Codeforces #653 (Div. 3)
A. Required Remainder
n を x で割った際の余りが y より大きければ割った際の商に x をかけて y を足したものが答えで、
それ以外ならば n を x で割った際の商から 1 を引いたものに x をかけて y を足したものが答えです。
提出したソースコードB. Multiply by 2, divide by 6
n を 2 と 3 についてのみ素因数分解して、残りが 1 でない場合は -1 です。
また、3 の個数が 2 の個数よりも少ない場合は -1 です。
それ以外の場合は 3 の個数に 3 の個数から 2 の個数を引いたものを足した数が答えです。
提出したソースコードC. Move Brackets
( と ) の個数をそれぞれ数え、 ) の個数が ( の個数を超えた場合は ) を一番右に移動したとみなして、答えに 1 を足し、( と ) の数を合わせます。
提出したソースコード
yukicoder
- No.1081 和の和
実験してみると、数列の各項は二項係数の数だけかけられていることがわかります。
あとは計算していくだけです。
提出したソースコード
競プロ精進日記 #57
精進や復習で解いた問題を載せていきます。
yukicoder
No.894 二種類のバス
普通に LCM を求めるとオーバーフローします。
解説にもあるような式変形をしましょう。
提出したソースコードNo.1070 Missing a space
S の 2 文字目から最後まで見ていき、0 以外が出たら答えに 1 を加算していきます。
提出したソースコードNo.1092 modular arithmetic
mod 上での演算を行います。
足し算、掛け算はそのまま行えば良いですが、
引き算をする際には mod p を取る前に、値が負になっていないこと、もし負になっていた場合は p を足すことを忘れないようにします。
また、mod 上での割り算はフェルマーの小定理から求めることができます。(参考)
提出したソースコード
競プロ精進日記 #56
精進や復習で解いた問題を載せていきます。
yukicoder
No.1091 Range Xor Query
累積 xor をします。
ちなみにセグメント木ペタリでもいけます。
提出したソースコード(累積 xor)
提出したソースコード(セグメント木解)No.1093 区間の和 / Sum of Range
累積和を取って S に値を入れていき、S をソートします。
その後 upper_bound で二分探索していけば良いです。
提出したソースコードNo.1094 木登り / Climbing tree
LCA をペタリとしましょう。
提出したソースコード
yukicoder No.1094 木登り / Climbing tree 解説
問題概要
- N 頂点の重みつき無向木が与えられる
- Q 個の質問 (以下) に答える
となる に関して、頂点 と頂点 の最短距離を求める
考えたこと
各頂点間の重みが 1 の場合はこの問題のように LCA を用いることで任意の 2 頂点間の最短距離を求めることができる。
各辺に重みを載せてあげれば同様に LCA を用いて任意の 2 頂点間の最短距離を求めることができそう。
実装
#include <bits/stdc++.h> using namespace std; template <typename T> class LCA { public: int n, log_v = 0; vector<int> depth; vector<T> costs; vector<vector<int> > to; vector<vector<T> > cost; vector<vector<int> > parent; LCA() {} LCA(int n_): n(n_) { while ((1 << log_v) < n) ++log_v; depth.assign(n, 0); costs.assign(n, 0); to = vector<vector<int> >(n); cost = vector<vector<T> >(n); parent = vector<vector<int> >(log_v, vector<int>(n, 0)); } void init(int root = 0) { dfs(root); for (int i = 0; i < log_v - 1; ++i) { rep (j, n) parent[i + 1][j] = parent[i][parent[i][j]]; } } void addEdge(int u, int v, T c = 0) { to[u].push_back(v); to[v].push_back(u); cost[u].push_back(c); cost[v].push_back(c); } void dfs(int v, int p = -1, int d = 0, T c = 0) { if (p != -1) parent[0][v] = p; depth[v] = d; costs[v] = c; for (int i = 0; i < to[v].size(); ++i) { int e = to[v][i]; if (e == p) continue; dfs(e, v, d + 1, c + cost[v][i]); } } int query(int u, int v) { if (depth[u] > depth[v]) swap(u, v); for (int i = 0; i < log_v; ++i) { if ((depth[v] - depth[u]) >> i & 1) v = parent[i][v]; } if (u == v) return u; for (int i = log_v - 1; i >= 0; --i) { if (parent[i][u] != parent[i][v]) { u = parent[i][u]; v = parent[i][v]; } } return parent[0][u]; } int length(int u, int v) { return depth[u] + depth[v] - 2 * depth[query(u, v)]; } T dist(int u, int v) { return costs[u] + costs[v] - 2 * costs[query(u, v)]; } // is x on the path u - v bool isOnPath(int u, int v, int x) { return length(u, x) + length(v, x) == length(u, v); } }; int main() { int n, q; cin >> n; LCA<int> lca = LCA<int>(n); for (int i = 0; i < n - 1; ++i) { int a, b, c; cin >> a >> b >> c; lca.addEdge(a - 1, b - 1, c); } lca.init(); cin >> q; for (int i = 0; i < q; ++i) { int s, t; cin >> s >> t; cout << lca.dist(s - 1, t - 1) << endl; } return 0; }
終わり
確か AtCoder の解説放送で LCA やっていた気がします。
解説放送ライブラリにもあってそれを参考にしてライブラリを作った気が。。。