結果
問題 | No.1054 Union add query |
ユーザー | SSRS |
提出日時 | 2022-09-21 04:56:26 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 811 ms / 2,000 ms |
コード長 | 3,320 bytes |
コンパイル時間 | 1,975 ms |
コンパイル使用メモリ | 183,656 KB |
実行使用メモリ | 62,428 KB |
最終ジャッジ日時 | 2024-06-01 17:18:59 |
合計ジャッジ時間 | 9,133 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,248 KB |
testcase_02 | AC | 2 ms
5,376 KB |
testcase_03 | AC | 654 ms
22,124 KB |
testcase_04 | AC | 795 ms
62,428 KB |
testcase_05 | AC | 615 ms
14,864 KB |
testcase_06 | AC | 637 ms
47,472 KB |
testcase_07 | AC | 595 ms
47,528 KB |
testcase_08 | AC | 550 ms
47,304 KB |
testcase_09 | AC | 811 ms
60,028 KB |
testcase_10 | AC | 322 ms
59,860 KB |
コンパイルメッセージ
main.cpp:80:9: warning: #pragma once in main file 80 | #pragma once | ^~~~
ソースコード
#include <bits/stdc++.h> using namespace std; struct unionfind{ vector<int> r, p; int t; unionfind(int N): r(N * 2 - 1, -1), p(N * 2 - 1, -1), t(N){ } int root(int x){ if (r[x] == -1){ return x; } else { r[x] = root(r[x]); return r[x]; } } bool same(int x, int y){ return root(x) == root(y); } void unite(int x, int y){ x = root(x); y = root(y); if (x != y){ p[x] = t; p[y] = t; r[x] = t; r[y] = t; t++; } } }; const int LOG = 17; struct lowest_common_ancestor{ vector<int> d; vector<vector<int>> pp; lowest_common_ancestor(vector<int> &p, vector<int> &d): d(d){ int N = p.size(); pp = vector<vector<int>>(LOG, vector<int>(N, -1)); pp[0] = p; for (int i = 0; i < LOG - 1; i++){ for (int j = 0; j < N; j++){ if (pp[i][j] != -1){ pp[i + 1][j] = pp[i][pp[i][j]]; } } } } int la(int v, int k){ for (int i = 0; i < LOG; i++){ if ((k >> i & 1) == 1){ v = pp[i][v]; } } return v; } int lca(int u, int v){ if (d[u] > d[v]){ swap(u, v); } v = la(v, d[v] - d[u]); if (u == v){ return u; } for (int i = LOG - 1; i >= 0; i--){ if (pp[i][u] != pp[i][v]){ u = pp[i][u]; v = pp[i][v]; } } return pp[0][v]; } }; void dfs(vector<vector<int>> &c, vector<int> &in, vector<int> &out, int &t, int v){ in[v] = t; t++; for (int w : c[v]){ dfs(c, in, out, t, w); } out[v] = t; } #pragma once /** * @brief 双対可逆 Binary Indexed Tree */ template <typename T> struct dual_invertible_binary_indexed_tree{ int N; vector<T> BIT; function<T(T, T)> f; function<T(T)> inv; T E; dual_invertible_binary_indexed_tree(int N, function<T(T, T)> f, function<T(T)> inv, T E): N(N), BIT(N + 1, E), f(f), inv(inv), E(E){ } void add(int i, T x){ while (i > 0){ BIT[i] = f(BIT[i], x); i -= i & -i; } } void add(int l, int r, T x){ add(l, inv(x)); add(r, x); } T operator [](int i){ i++; T ans = E; while (i <= N){ ans = f(ans, BIT[i]); i += i & -i; } return ans; } }; int main(){ int N, Q; cin >> N >> Q; unionfind UF(N); vector<tuple<int, int, int>> query; for (int i = 0; i < Q; i++){ int T, A, B; cin >> T >> A >> B; if (T == 1){ A--; B--; UF.unite(A, B); } if (T == 2){ A--; query.push_back(make_tuple(0, UF.root(A), B)); } if (T == 3){ A--; query.push_back(make_tuple(1, A, 0)); } } vector<int> p = UF.p; p.push_back(-1); for (int i = 0; i < N * 2 - 1; i++){ if (p[i] == -1){ p[i] = N * 2 - 1; } } vector<vector<int>> c(N * 2); for (int i = 0; i < N * 2 - 1; i++){ c[p[i]].push_back(i); } vector<int> in(N * 2), out(N * 2); int t = 0; dfs(c, in, out, t, N * 2 - 1); dual_invertible_binary_indexed_tree<int> BIT(N * 2, plus<int>(), negate<int>(), 0); int M = query.size(); for (int i = 0; i < M; i++){ if (get<0>(query[i]) == 0){ int v = get<1>(query[i]); int x = get<2>(query[i]); BIT.add(in[v], out[v], x); } if (get<0>(query[i]) == 1){ int v = get<1>(query[i]); cout << BIT[in[v]] << endl; } } }