• P3402 【模板】可持久化并查集


    这个题竟然没有用什么新算法,就是用主席树随便搞搞就过了。。。代码好像也很好理解。

    题干:

    n个集合 m个操作
    
    操作:
    
    1 a b 合并a,b所在集合
    
    2 k 回到第k次操作之后的状态(查询算作操作)
    
    3 a b 询问a,b是否属于同一集合,是则输出1否则输出0
    
    输入输出格式
    输入格式:
    输出格式:
    输入输出样例
    输入样例#15 6
    1 1 2
    3 1 2
    2 0
    3 1 2
    2 1
    3 1 2
    输出样例#11
    0
    1
    说明
    1 le n le 10^5, 1 le m le 2 	imes 10^51≤n≤10 
    5
     ,1≤m≤2×10 
    5
     
    By zky 出题人大神犇

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<ctime>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    #define duke(i,a,n) for(register int i = a;i <= n;i++)
    #define lv(i,a,n) for(register int i = a;i >= n;i--)
    #define clean(a) memset(a,0,sizeof(a))
    const int INF = 1 << 30;
    typedef long long ll;
    typedef double db;
    template <class T>
    void read(T &x)
    {
        char c;
        bool op = 0;
        while(c = getchar(), c < '0' || c > '9')
            if(c == '-') op = 1;
        x = c - '0';
        while(c = getchar(), c >= '0' && c <= '9')
            x = x * 10 + c - '0';
        if(op) x = -x;
    }
    template <class T>
    void write(T x)
    {
        if(x < 0) putchar('-'), x = -x;
        if(x >= 10) write(x / 10);
        putchar('0' + x % 10);
    }
    const int N = 200010;
    struct node
    {
        int l,r;
    }tree[N * 30];
    int rt[N * 30],tot = 0,fa[N * 30],dep[N * 30];
    int n,m;
    void build(int &now,int l,int r)
    {
        now = ++tot;
        if(l == r)
        {
            fa[now] = l;
            return;
        }
        int mid = (l + r) >> 1;
        build(tree[now].l,l,mid);
        build(tree[now].r,mid + 1,r);
    }
    void update(int &now,int lst,int l,int r,int pos,int ff)
    {
        now = ++tot;
        if(l == r)
        {
            fa[now] = ff;
            dep[now] = dep[lst];
            return;
        }
        tree[now] = tree[lst];
        int mid = (l + r) >> 1;
        if(pos <= mid) update(tree[now].l,tree[lst].l,l,mid,pos,ff);
        else update(tree[now].r,tree[lst].r,mid + 1,r,pos,ff);
    }
    int query(int now,int l,int r,int pos)
    {
        if(l == r)
        {
            return now;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)
        return query(tree[now].l,l,mid,pos);
        else
        return query(tree[now].r,mid + 1,r,pos);
    }
    void add(int now,int l,int r,int pos)
    {
        if(l == r)
        {
            ++dep[now];
            return;
        }
        int mid = (l + r) >> 1;
        if(pos <= mid)
        add(tree[now].l,l,mid,pos);
        else
        add(tree[now].r,mid + 1,r,pos);
    }
    int find_fa(int now,int x)
    {
        int ff = query(now,1,n,x);
        if(x == fa[ff]) return ff;
        return find_fa(now,fa[ff]);
    }
    int main()
    {
        read(n);read(m);
        build(rt[0],1,n);
        int opt,a,b,k;
        duke(i,1,m)
        {
            read(opt);
            if(opt == 1)
            {
                rt[i] = rt[i - 1];
                read(a);read(b);
                int f1 = find_fa(rt[i],a);
                int f2 = find_fa(rt[i],b);
                if(fa[f1] == fa[f2]) continue;
                if(dep[f1] > dep[f2]) swap(f1,f2);
                update(rt[i],rt[i - 1],1,n,fa[f1],fa[f2]);
                if(dep[f1] == dep[f2]) add(rt[i],1,n,fa[f2]);
            }
            if(opt == 2)
            {
                read(k);
                rt[i] = rt[k];
            }
            if(opt == 3)
            {
                rt[i] = rt[i - 1];
                read(a);read(b);
                int f1 = find_fa(rt[i],a);
                int f2 = find_fa(rt[i],b);
                if(f1 == f2) puts("1");
                else puts("0");
            }
        }
        return 0;
    }
  • 相关阅读:
    bert中的为什么
    ROS+Ubuntu+VSCode
    致我成为社畜的第一年
    SQL实战 11.高频SQL面试题 课程订单分析系列
    SQL实战 10.高频SQL面试题 考试分数系列
    SQL实战 9.高频SQL面试题 网站访客最近登录日期系列
    SQL实战 8.异常的邮件概率 sum、count、round和case when结合
    SQL实战 7刷题通过的题目排名 row_number、 dense_rank 和rank区别
    SQL实战 6.对于employees表中,给出奇数行的first_name
    SQL实战 5.统计salary的累计和running_total
  • 原文地址:https://www.cnblogs.com/DukeLv/p/10253435.html
Copyright © 2020-2023  润新知