1. 程式人生 > >BZOJ 3674 可持久化並查集加強版(主席樹變形)

BZOJ 3674 可持久化並查集加強版(主席樹變形)

als ret desc scan sync scanf ops 只需要 ica

3673: 可持久化並查集 by zky

Time Limit: 5 Sec Memory Limit: 128 MB
Submit: 2515 Solved: 1107
[Submit][Status][Discuss]

Description

n個集合 m個操作
操作:
1 a b 合並a,b所在集合
2 k 回到第k次操作之後的狀態(查詢算作操作)
3 a b 詢問a,b是否屬於同一集合,是則輸出1否則輸出0

0<n,m<=2*10^4

Input

Output

Sample Input

5 6
1 1 2
3 1 2
2 0
3 1 2
2 1
3 1 2

Sample Output

1
0
1

HINT

Source

出題人大SB

題目鏈接:BZOJ 3674

原來並查集也是可以可持久化的,其思想應該是在於用可持久化數據結構來維護一個前綴記錄,由於普通的並查集一開始每一個節點的祖先都是本身,因此要多一個建樹的操作,把所有的葉子節點的祖先都處理好,然後這題是並查集,並不需要差分的思想,也就是說更新或者查詢只需要用到一個root點,

其他的做法跟普通的並查集差不多,詳細的可以看黃大牛的博客:http://hzwer.com/3997.html。

代碼:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 2e5 + 7;
struct seg
{
    int lson, rson;
    int pre;
};
seg T[N * 40];
int root[N], tot;
int n;

void init()
{
    CLR(root, 0);
    tot = 0;
}
void build(int &cur, int l, int r)
{
    cur = ++tot;
    T[cur].lson = T[cur].rson = 0;
    if (l == r)
        T[cur].pre = l;
    else
    {
        int mid = MID(l, r);
        build(T[cur].lson, l, mid);
        build(T[cur].rson, mid + 1, r);
    }
}
void update(int &cur, int ori, int l, int r, int pos, int pre)
{
    cur = ++tot;
    T[cur] = T[ori];
    if (l == r)
    {
        T[cur].pre = pre;
        return ;
    }
    else
    {
        int mid = MID(l, r);
        if (pos <= mid)
            update(T[cur].lson, T[ori].lson, l, mid, pos, pre);
        else
            update(T[cur].rson, T[ori].rson, mid + 1, r, pos, pre);
    }
}
int query(int k, int l, int r, int pos) //返回子節點位置
{
    if (l == r)
        return k;
    else
    {
        int mid = MID(l, r);
        if (pos <= mid)
            return query(T[k].lson, l, mid, pos);
        else
            return query(T[k].rson, mid + 1, r, pos);
    }
}
int Find(int k, int pre)
{
    int idx = query(k, 1, n, pre);
    if (pre == T[idx].pre)
        return pre;
    else
        return Find(k, T[idx].pre);
}
int main(void)
{
    int m, i, a, b, k, ops;
    while (~scanf("%d%d", &n, &m))
    {
        init();
        int ans = 0;
        build(root[0], 1, n);
        for (i = 1; i <= m; ++i)
        {
            scanf("%d", &ops);
            if (ops == 1)
            {
                scanf("%d%d", &a, &b);
                a ^= ans;
                b ^= ans;
                root[i] = root[i - 1];
                int fa = Find(root[i], a);
                int fb = Find(root[i], b);
                if (fa != fb)
                    update(root[i], root[i - 1], 1, n, fb, fa);
            }
            else if (ops == 2)
            {
                scanf("%d", &k);
                k ^= ans;
                root[i] = root[k];
            }
            else if (ops == 3)
            {
                scanf("%d%d", &a, &b);
                a ^= ans;
                b ^= ans;
                root[i] = root[i - 1];
                int fa = Find(root[i], a);
                int fb = Find(root[i], b);
                printf("%d\n", ans = (fa == fb));
            }
        }
    }
    return 0;
}

BZOJ 3674 可持久化並查集加強版(主席樹變形)