• BZOJ 3319 黑白树


    一道神奇的并查集。

    一眼看是树剖,但是会被卡。

    有人用线段树+并查集卡过了。

    然而可以做到O(n)。

    抄的题解

    先把所有点往他父亲的边变黑的时间记在col中,染黑。然后把没变黑的点用并查集合并。倒着做一遍把该时间点的边染白,用并查集合并。

    //Twenty
    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<queue>
    #include<vector>
    typedef long long LL;
    const int maxn=1e6+299;
    using namespace std;
    int n,m,fir[maxn],nxt[maxn*2],to[maxn*2],id[maxn*2],p[maxn],fa[maxn],ecnt;
    int col[maxn],R[maxn],lz[maxn];
    struct egde{
        int op,x,y,ans;
    }e[maxn];
    void add(int u,int v,int i) {
        nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; id[ecnt]=i;
        nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u; id[ecnt]=i;
    }
    int find(int x) {
        return x==fa[x]?x:fa[x]=find(fa[x]);
    }
    void dfs(int x,int f) {
        p[x]=f; R[x]=R[f]+1;
        for(int i=fir[x];i;i=nxt[i]) if(to[i]!=f) {
            lz[to[i]]=id[i];
            dfs(to[i],x);
        }
    }
    void change(int x,int y,int ti) {
        while(x!=y) {
            if(R[x]<R[y]) swap(x,y);
            if(!col[x]) fa[x]=fa[p[x]],col[x]=ti; 
            x=fa[x];
        }
    }
    void schange(int x,int y,int ti) {
         while(x!=y) {
             if(R[x]<R[y]) swap(x,y);
             if(col[x]==ti) fa[x]=fa[p[x]];
             x=p[x];
          }
    }
    int main()
    {
        //freopen(".in","r",stdin);
        //freopen(".out","w",stdout);
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++) {
            int u,v;
            scanf("%d%d",&u,&v);
            add(u,v,i);
        }
        dfs(1,1);
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<=m;i++) {
            scanf("%d%d",&e[i].op,&e[i].x);
            if(e[i].op==2) {
                scanf("%d",&e[i].y);
                change(e[i].x,e[i].y,i);
            }
        }
        for(int i=1;i<=n;i++) fa[i]=i;
        for(int i=1;i<=n;i++) {
             if(!col[i]) {
                 fa[i]=fa[p[i]];
            }
         }
         for(int i=m;i>=1;i--) {
             if(e[i].op==1) {
                 int x=find(e[i].x);
                 e[i].ans=lz[x];
            }
            else {
                schange(e[i].x,e[i].y,i);
            }
         }
         for(int i=1;i<=m;i++) if(e[i].op==1) printf("%d
    ",e[i].ans);
        return 0;
    }
    View Code
  • 相关阅读:
    Oracle 11g R2(11.2.0.4.0)+udev搭建RAC
    在 Linux 中用 nmcli 命令绑定多块网卡
    linux 配置聚合连接team(网卡绑定) , systemd 控制
    7.linux目录结构
    6.VMware备份linux操作系统
    5.linux关机和切换运行模式
    4.linux安装
    linux网络配置知识
    3.Virtual Box的安装
    2.vmWare安装
  • 原文地址:https://www.cnblogs.com/Achenchen/p/7603479.html
Copyright © 2020-2023  润新知