离线做法 / 并查集与主席树的结合

顾名思义,就是可持久化的并查集————即支持历史版本回溯的并查集。

比如NOI2018d1t1的两个log做法。

通常实现方法

离线做法

注意到按秩合并的并查集是支持撤销的(注意“撤销”和“删除”是两码事)。

于是与其他离线题目类似,在操作的拓扑图上顺序做下就行了(空间又小跑得还快)。

 1 #include<bits/stdc++.h>
 2 const int maxn = 100035;
 3 const int maxm = 200035;
 4 
 5 struct QRs
 6 {
 7     int opt,x,y;
 8 }q[maxm];
 9 struct DSU
10 {
11     int top,stk[maxn],fa[maxn],tot[maxn];
12     void init()
13     {
14         top = 0;
15         for (int i=1; i<maxn; i++) fa[i] = i, tot[i] = 1;
16     }
17     int get(int x){return x==fa[x]?x:get(fa[x]);}
18     void unions(int x, int y)
19     {
20         int fx = get(x), fy = get(y);
21         if (fx==fy) return;
22         if (tot[fx] < tot[fy]) std::swap(fx, fy);
23         fa[fy] = fx, tot[fx] += tot[fy];
24         stk[++top] = fy;
25     }
26     void back(int t)
27     {
28         while (top > t)
29         {
30             int x = stk[top--];
31             tot[fa[x]] -= tot[x], fa[x] = x;
32         }
33     }
34 }f;
35 int ans[maxm];
36 int n,m;
37 int edgeTot,edges[maxm],nxt[maxm],head[maxm];
38 
39 inline int read()
40 {
41     char ch = getchar();
42     int num = 0;
43     bool fl = 0;
44     for (; !isdigit(ch); ch = getchar())
45         if (ch=='-') fl = 1;
46     for (; isdigit(ch); ch = getchar())
47         num = (num<<1)+(num<<3)+ch-48;
48     if (fl) num = -num;
49     return num;
50 }
51 void addedge(int u, int v)
52 {
53     edges[++edgeTot] = v, nxt[edgeTot] = head[u], head[u] = edgeTot;
54 }
55 void dfs(int x)
56 {
57     int t = f.top;
58     if (q[x].opt==3) ans[x] = f.get(q[x].x)==f.get(q[x].y)?1:0;
59     if (q[x].opt==1) f.unions(q[x].x, q[x].y);
60     for (int i=head[x]; i!=-1; i=nxt[i])
61         dfs(edges[i]);
62     f.back(t);
63 }
64 int main()
65 {
66     memset(head, -1, sizeof head);
67     n = read(), m = read(), f.init();
68     for (int i=1; i<=m; i++)
69     {
70         q[i].opt = read(), q[i].x = read();
71         if (q[i].opt==2) addedge(q[i].x, i);
72         else q[i].y = read(), addedge(i-1, i);
73     }
74     dfs(0);
75     for (int i=1; i<=m; i++)
76         if (q[i].opt==3) printf("%d\n",ans[i]);
77     return 0;
78 }
离线做法

相关文章:

  • 2022-03-01
  • 2022-02-26
  • 2021-06-18
  • 2022-03-05
  • 2021-07-14
  • 2022-12-23
猜你喜欢
  • 2021-10-06
  • 2021-12-27
  • 2021-05-28
  • 2021-12-31
相关资源
相似解决方案