結果
| 問題 |
No.1054 Union add query
|
| コンテスト | |
| ユーザー |
SSRS
|
| 提出日時 | 2022-09-21 04:58:03 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 823 ms / 2,000 ms |
| コード長 | 3,257 bytes |
| コンパイル時間 | 2,131 ms |
| コンパイル使用メモリ | 184,920 KB |
| 実行使用メモリ | 63,096 KB |
| 最終ジャッジ日時 | 2024-12-22 04:01:11 |
| 合計ジャッジ時間 | 8,298 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge4 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 3 |
| other | AC * 8 |
ソースコード
#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;
}
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;
}
}
}
SSRS