結果
問題 | No.529 帰省ラッシュ |
ユーザー | Pachicobue |
提出日時 | 2017-12-31 03:16:22 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
RE
|
実行時間 | - |
コード長 | 10,932 bytes |
コンパイル時間 | 3,335 ms |
コンパイル使用メモリ | 238,152 KB |
実行使用メモリ | 10,656 KB |
最終ジャッジ日時 | 2024-06-01 08:58:28 |
合計ジャッジ時間 | 11,115 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,812 KB |
testcase_01 | AC | 2 ms
6,940 KB |
testcase_02 | AC | 2 ms
6,944 KB |
testcase_03 | AC | 2 ms
6,940 KB |
testcase_04 | RE | - |
testcase_05 | RE | - |
testcase_06 | TLE | - |
testcase_07 | -- | - |
testcase_08 | -- | - |
testcase_09 | -- | - |
testcase_10 | -- | - |
testcase_11 | -- | - |
testcase_12 | -- | - |
testcase_13 | -- | - |
testcase_14 | -- | - |
testcase_15 | -- | - |
testcase_16 | -- | - |
testcase_17 | -- | - |
testcase_18 | -- | - |
testcase_19 | -- | - |
ソースコード
#include <bits/stdc++.h> using namespace std; using ll = long long; using P = pair<int, int>; template <typename T> constexpr T INF = numeric_limits<T>::max() / 10; struct Graph { Graph(const int v) : V{v} { edge.resize(v); rev_edge.resize(v); } void addEdge(const int from, const int to) { edge[from].push_back(to); rev_edge[to].push_back(from); } vector<vector<int>> edge; vector<vector<int>> rev_edge; const int V; }; class BiconnectedComponent { public: BiconnectedComponent(const Graph& g_) : num{0}, comp_num{0}, size{g_.V}, bridge(0), ord(size, -1), low(size, 0), comp(size, -1) { for (int i = 0; i < size; i++) { if (ord[i] == -1) { bridge_dfs(g_, i); } } for (int i = 0; i < size; i++) { if (comp[i] >= 0) { continue; } comp_dfs(g_, i, comp_num); comp_num++; } } Graph toTree() const { Graph tree(comp_num); for (const auto& p : bridge) { tree.addEdge(comp[p.first], comp[p.second]); tree.addEdge(comp[p.second], comp[p.first]); } return tree; } const vector<pair<int, int>>& getEdge() const { return bridge; } bool isBridge(const int i, const int j) const { return (ord[i] < ord[j]) ? ord[i] < low[j] : ord[j] < low[i]; } const vector<int>& getComp() const { return comp; } const vector<pair<int, int>>& getBridge() const { return bridge; } private: void bridge_dfs(const Graph& g_, const int s, const int par = -1) { ord[s] = num; low[s] = num; num++; for (const int to : g_.edge[s]) { if (to == par) { continue; } if (ord[to] >= 0) { low[s] = min(low[s], ord[to]); } else { bridge_dfs(g_, to, s); low[s] = min(low[s], low[to]); if (isBridge(s, to)) { bridge.push_back(make_pair(s, to)); } } } } void comp_dfs(const Graph& g_, const int s, const int c) { comp[s] = c; for (const int to : g_.edge[s]) { if ((comp[to] == -1) and (not isBridge(s, to))) { comp_dfs(g_, to, c); } } } int num; int comp_num; const int size; vector<pair<int, int>> bridge; vector<int> ord; vector<int> low; vector<int> comp; }; class HeavyLightDecomposition { private: using P = pair<int, int>; public: HeavyLightDecomposition(const Graph& g, const int root = 0) : N(g.V), sub(N, 0), prev(N, -1), next(N, -1), depth(N, 0), head{root}, index(N, {-1, 0}), chains(0) { dfs(g, root, 0); chains.resize(head.size()); for (int i = 0; i < head.size(); i++) { int pos = head[i]; int v = -1; for (int ind = 0; pos != -1; ind++) { v = pos; chains[i].push_back(pos); index[pos] = {i, ind}; pos = next[pos]; } tail.push_back(v); } } P getIndex(const int v) const { return index[v]; } int getChainIndex(const int v) const { return index[v].first; } int getPosition(const int v) const { return index[v].second; } int getHead(const int v) const { return head[index[v].first]; } int getTail(const int v) const { return tail[index[v].first]; } const vector<int>& getDepth() const { return depth; } int prevChainNode(const int v) const { return prev[getHead(v)]; } P prevChainIndex(const int v) const { return getIndex(prevChainNode(v)); } int getLCA(int u, int v) const { while (getChainIndex(u) != getChainIndex(v)) { if (depth[getHead(u)] > depth[getHead(v)]) { u = prevChainNode(u); } else { v = prevChainNode(v); } } return depth[u] < depth[v] ? u : v; } const vector<vector<int>>& getChains() const { return chains; } int prevChain(const int v) const { return prev[head[index[v].first]]; } const int N; private: int dfs(const Graph& g, const int s, const int d) { sub[s] = 1; depth[s] = d; vector<P> child; for (const int to : g.edge[s]) { if (sub[to] == 0) { prev[to] = s; const int s = dfs(g, to, d + 1); sub[s] += s; child.push_back({s, to}); } } sort(child.begin(), child.end(), greater<P>{}); if (child.size()) { next[s] = child[0].second; for (int i = 1; i < child.size(); i++) { head.push_back(child[i].second); } } return sub[s]; } vector<int> sub; vector<int> prev; vector<int> next; vector<int> tail; vector<int> depth; vector<int> head; vector<P> index; vector<vector<int>> chains; }; template <typename Monoid> class FenwickTree { public: using BaseMonoid = Monoid; using T = typename Monoid::T; FenwickTree(const int n) : data_num(n), size(1 << (1 + __lg(2 * data_num - 1))), half(size >> 1), value(size, Monoid::identity()) { assert(n > 0); } FenwickTree(const std::vector<T>& val) : data_num(val.size()), size(1 << (1 + __lg(2 * data_num - 1))), half(size >> 1), value(size) { for (int data = 0; data < half; data++) { if (data < data_num) { value[data + half] = val[data]; } else { value[data + half] = Monoid::identity(); } } for (int node = half - 1; node >= 1; node--) { value[node] = acc(value[2 * node], value[2 * node + 1]); } } T get(const int a) const { assert(0 <= a and a < data_num); return accumulate(a, a + 1); } void set(const int a, const T& val) { assert(0 <= a and a < data_num); const int node = a + half; value[node] = val; for (int i = node / 2; i > 0; i /= 2) { value[i] = acc(value[2 * i], value[2 * i + 1]); } } T accumulate(const int a, const int b) const // Accumulate (a,b] { assert(0 <= a and a < b and b <= data_num); return accumulateRec(1, 0, half, a, b); } int query(const int a, const int b) const // query (a,b] { assert(0 <= a and a < b and b <= data_num); return queryRec(1, 0, half, a, b); } private: T accumulateRec(const int range_index, const int range_left, const int range_right, const int op_left, const int op_right) const { if (op_left <= range_left and range_right <= op_right) { return value[range_index]; } else if (range_right <= op_left or op_right <= range_left) { return Monoid::identity(); } else { return acc(accumulateRec(2 * range_index, range_left, (range_left + range_right) / 2, op_left, op_right), accumulateRec(2 * range_index + 1, (range_left + range_right) / 2, range_right, op_left, op_right)); } } int queryRec(const int range_index, const int range_left, const int range_right, const int op_left, const int op_right) const { if (op_left <= range_left and range_right <= op_right) { return value[range_index]; } else if (range_right <= op_left or op_right <= range_left) { return Monoid::identity(); } else { return queryRec(2 * range_index, range_left, (range_left + range_right) / 2, op_left, op_right) + queryRec(2 * range_index + 1, (range_left + range_right) / 2, range_right, op_left, op_right); } } const int data_num; // Num of valid data on leaves. const int size; const int half; vector<T> value; // Tree for value(length: size) const Monoid acc{}; }; struct Max { using T = pair<ll, int>; T operator()(const T& a, const T& b) const { return max(a, b); } static constexpr T identity() { return make_pair(-INF<ll>, -1); } }; int main() { cin.tie(0); ios::sync_with_stdio(false); int N, M, Q; cin >> N >> M >> Q; Graph g_(N); for (int i = 0; i < M; i++) { int a, b; cin >> a >> b; a--, b--; g_.addEdge(a, b); g_.addEdge(b, a); } BiconnectedComponent bic(g_); const int comp = bic.getComp().size(); auto g = bic.toTree(); vector<priority_queue<ll>> value(comp); HeavyLightDecomposition hld(g); vector<FenwickTree<Max>> segs; for (const auto& chain : hld.getChains()) { vector<pair<ll, int>> v(chain.size()); for (int i = 0; i < chain.size(); i++) { v[i] = {-1, i}; } segs.push_back(FenwickTree<Max>{v}); } for (int q = 0; q < Q; q++) { int t; cin >> t; if (t == 1) { int u; ll v; cin >> u >> v; u--; const int comp = bic.getComp()[u]; value[comp].push(v); const P chind = hld.getIndex(comp); segs[chind.first].set(chind.second, {value[comp].top(), chind.second}); } else { int s, t; cin >> s >> t; s--, t--; s = bic.getComp()[s]; t = bic.getComp()[t]; const int lca = hld.getLCA(s, t); const P lca_ch = hld.getIndex(lca); int pos[2] = {s, t}; pair<ll, int> ans{-1, -1}; int maxchain = -1; for (int i = 0; i < 2; i++) { while (true) { const P index = hld.getIndex(pos[i]); const int head = (lca_ch.first == index.first ? lca_ch.second : 0); const auto val = segs[index.first].accumulate(head, index.second + 1); if (ans < val) { ans = val; maxchain = index.first; } if (lca_ch.first == index.first) { break; } pos[i] = hld.prevChainNode(pos[i]); } } if (ans.first > 0) { const int node = hld.getChains()[maxchain][ans.second]; value[node].pop(); const ll val = (value[node].empty() ? -1 : value[node].top()); segs[maxchain].set(ans.second, make_pair(val, ans.second)); } cout << ans.first << endl; } } return 0; }