带权并查集

Nannan Lv5

Weighted Disjoint-set(带权并查集)

eg带权并查集

给你个变量,一开始不知道这些数是多少。

你要执行次操作。

  • 1 l r x,给你一条线索,表示,如果与已知条件矛盾,那么忽略这次操作。
  • 2 l r回答,如果现在的线索无法推出答案,那么忽略这次操作。

强制在线(读一个操作一个):

有一个变量,一开始,每次未被忽略的查询操作之后,会变成答案的绝对值,也就是。每次操作输入的是加密后的实际上的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 201000;
int n,q,fa[N];
ll w[N];

int find(int x)
{
if(x==fa[x])return x;
int p = fa[x];
find(p);//先把fa[x]做一个路径压缩,假设现在的fa[p] = q
/*
w[x] = a[x]-a[p]
fa[p] = q , w[p]:a[p]-a[q]
fa[x] = p , w[x]:a[x]-a[p]
a[x] - a[p] + a[p] - a[q] = a[x]+a[p]
*/
w[x] = w[x]+w[p];
return fa[x] = fa[p];
}

int main()
{
cin>>n>>q;
//w[i] = a[i]-a[fa[i]];
for(int i = 1;i<=n;i++)fa[i] = i,w[i] = 0;
ll t = 0;
for(int i = 0;i<q;i++)
{
int op,l,r;
cin>>op>>l>>r;
l = (l+t)%n + 1;
r = (r+t)%n + 1;
if(op==2)
{
if(find(l)!=find(r))continue;
else cout<<w[l]-w[r]<<endl;
t = abs(w[l]-w[r]);
}
else if(op==1)
{
int x;
cin>>x;
if(find(l)==find(r))continue;
/*
w[fa[l]] = a[fa[l]]-a[fa[r]];
a[l]-a[r] = x;
w[l] = a[l]-a[fa[l]],w[r] = a[r]-a[fa[r]];
a[l] - w[l] = a[fa[l]],a[r]-w[r] = a[fa[r]]
w[fa[l]] = a[l]-w[l]-(a[r]-w[r])
*/
//先改权值再变父亲
w[fa[l]] = x-w[l]+w[r];
fa[fa[l]] = fa[r];
}
}
return 0;
}

  • Title: 带权并查集
  • Author: Nannan
  • Created at : 2023-08-12 22:01:00
  • Updated at : 2024-09-30 19:52:39
  • Link: https://redefine.ohevan.com/2023/08/12/四(3)、带权并查集Weighted Disjoint-set/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments