This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct DSU{
int path[100100];
void init(int n){
for (int i=1;i<=n;i++) path[i] = i;
}
int find(int s){
if (s==path[s]) return s;
return path[s] = find(path[s]);
}
bool merge(int s, int v){
s = find(s), v = find(v);
if (s==v) return false;
path[v] = s;
return true;
}
}dsu;
struct Seg{
int tree[400400], lazy[400400];
void init(int i, int l, int r){
lazy[i] = 0;
if (l==r){tree[i] = 1; return;}
int m = (l+r)>>1;
init(i<<1, l, m); init(i<<1|1, m+1, r);
tree[i] = tree[i<<1] + tree[i<<1|1];
}
void propagate(int i, int l, int r){
if (lazy[i]) tree[i] = 0;
else return;
if (l!=r){
lazy[i<<1] = 1;
lazy[i<<1|1] = 1;
}
lazy[i] = 0;
return;
}
void update(int i, int l, int r, int s, int e){
propagate(i, l, r);
if (r<s || e<l) return;
if (s<=l && r<=e){
lazy[i] = 1;
propagate(i, l, r);
return;
}
int m = (l+r)>>1;
update(i<<1, l, m, s, e); update(i<<1|1, m+1, r, s, e);
tree[i] = tree[i<<1] + tree[i<<1|1];
}
int query(int i, int l, int r, int s, int e){
propagate(i, l, r);
if (r<s || e<l) return 0;
if (s<=l && r<=e) return tree[i];
int m = (l+r)>>1;
return query(i<<1, l, m, s, e) + query(i<<1|1, m+1, r, s, e);
}
}tree;
vector<int> adj[100100], G[100100];
int dep[100100], par[100100], top[100100], sz[100100], in[100100], out[100100], cnt, n;
int T[300300], X[300300], Y[300300];
void dfs0(int s, int pa = 0){
par[s] = pa;
dep[s] = dep[pa] + 1;
sz[s] = 1;
for (auto &v:adj[s]) if (v!=pa){
G[s].push_back(v);
dfs0(v, s);
sz[s] += sz[v];
}
}
void dfs1(int s){
in[s] = ++cnt;
if (!G[s].empty()) swap(G[s][0], *max_element(G[s].begin(), G[s].end(), [&](int x, int y){
return sz[x] < sz[y];
}));
for (auto &v:G[s]){
if (v==G[s][0]) top[v] = top[s];
else top[v] = v;
dfs1(v);
}
out[s] = cnt;
}
int query(int x, int y, int t){
// printf("query %d %d / %d %d / %d %d\n", x, y, in[x], in[y], top[x], top[y]);
int ret = 0;
while(top[x]!=top[y]){
if (dep[top[x]] > dep[top[y]]) swap(x, y);
ret += tree.query(1, 1, n, in[top[y]], in[y]);
if (t==1) tree.update(1, 1, n, in[top[y]], in[y]);
y = par[top[y]];
}
if (dep[x] > dep[y]) swap(x, y);
// printf("ok %d to %d\n", in[x]+1, in[y]);
ret += tree.query(1, 1, n, in[x]+1, in[y]);
if (t==1) tree.update(1, 1, n, in[x]+1, in[y]);
return ret;
}
int main(){
int q;
scanf("%d %d", &n, &q);
dsu.init(n);
for (int i=1;i<=q;i++){
scanf("%d %d %d", T+i, X+i, Y+i);
if (T[i]==1){
if (dsu.merge(X[i], Y[i])){
adj[X[i]].push_back(Y[i]);
adj[Y[i]].push_back(X[i]);
}
}
}
vector<int> root;
for (int i=1;i<=n;i++) if (!par[i]){
root.push_back(i);
dfs0(i);
}
for (auto &r:root){
top[r] = r;
dfs1(r);
}
tree.init(1, 1, n);
dsu.init(n);
for (int i=1;i<=q;i++){
if (dsu.find(X[i])!=dsu.find(Y[i])){
if (T[i]==2){
printf("-1\n");
}
else{
dsu.merge(X[i], Y[i]);
}
}
else{
int ans = query(X[i], Y[i], T[i]);
if (T[i]==2) printf("%d\n", ans);
}
}
}
Compilation message (stderr)
road_development.cpp: In function 'int main()':
road_development.cpp:127:7: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
127 | scanf("%d %d", &n, &q);
| ~~~~~^~~~~~~~~~~~~~~~~
road_development.cpp:131:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
131 | scanf("%d %d %d", T+i, X+i, Y+i);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |