zoukankan      html  css  js  c++  java
  • 洛谷P3690 LCT模板

    题目:https://www.luogu.org/problemnew/show/P3690

    自己竟然从没有钻研过LCT上的连通性问题!

    于是被最后一个点卡了,似乎因为 find 函数只能找出连通性而不能判断有没有直接相连的边;

    所以还是直接在 cut 函数里判断一下好了。

    (注:第9个点时T时不T的,不想去管它了。)

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    int const maxn=3e5+5;
    int n,m,fa[maxn],c[maxn][3],sum[maxn],w[maxn],rev[maxn],sta[maxn],top;
    bool isroot(int x){return c[fa[x]][0]!=x && c[fa[x]][1]!=x;}
    void pushup(int x)
    {
        sum[x]=(sum[c[x][0]]^sum[c[x][1]]^w[x]);
    }
    void reverse(int x)
    {
        if(rev[x])
        {
            rev[c[x][0]]^=1; rev[c[x][1]]^=1; rev[x]=0;
            swap(c[x][0],c[x][1]);
        }
    }
    void rotate(int x)
    {
        int y=fa[x],z=fa[y],d=(c[y][1]==x);
        if(!isroot(y))c[z][c[z][1]==y]=x;
        fa[x]=z; fa[y]=x; fa[c[x][!d]]=y;
        c[y][d]=c[x][!d]; c[x][!d]=y;
        pushup(y); pushup(x);
    }
    void splay(int x)
    {
        sta[top=1]=x;
        for(int i=x;!isroot(i);i=fa[i])sta[++top]=fa[i];
        for(;top;top--)reverse(sta[top]);
        for(;!isroot(x);rotate(x))
        {
            int y=fa[x],z=fa[y];
            if(isroot(y))continue;
            ((c[y][0]==x)^(c[z][0]==y))?rotate(x):rotate(y);
        }
    }
    void access(int x)
    {
        for(int t=0;x;c[x][1]=t,pushup(x),t=x,x=fa[x])splay(x);
    }
    void makeroot(int x)
    {
        access(x); splay(x); rev[x]^=1;
    }
    void link(int x,int y)
    {
        makeroot(x); fa[x]=y;
    }
    void query(int x,int y)
    {
        makeroot(x); access(y); splay(y);
    }
    void cut(int x,int y)
    {
        query(x,y);
        if(c[y][0]!=x)return;//!
        fa[x]=0; c[y][0]=0;
    }
    int find(int x)
    {
        access(x); splay(x); while(c[x][0])x=c[x][0]; return x;
    }
    void change(int u,int t)
    {
        makeroot(u); w[u]=t; pushup(u);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&w[i]);
        for(int i=1,op,x,y;i<=m;i++)
        {
            scanf("%d%d%d",&op,&x,&y);
            if(op==0){query(x,y); printf("%d
    ",sum[y]);}
            if(op==1)
            {
                if(find(x)==find(y))continue;
                link(x,y);
            }
            if(op==2)
            {
    //            if(find(x)!=find(y))continue;
                cut(x,y);
            }
            if(op==3)change(x,y);
        }
        return 0;
    }
    /*
    5 6
    1
    2
    3
    4
    5
    1 1 2
    1 2 3
    1 3 4
    1 4 5
    2 1 5
    0 1 5
    
    
    1
    */
  • 相关阅读:
    CSS 对浏览器的兼容性技巧总结
    后台拿webshell的方法总结
    WEBSHELL权限提升技巧
    学习linq处理数据 遥远的青苹果
    在asp.net中怎么导出excel表
    SQL提取数据库记录按字的笔画排序
    主板前置音频线怎么接
    Oracle导入导出
    DevExpress GridControl界面汉化(摘自王铭)
    ASP.NET中如何防范SQL注入式攻击
  • 原文地址:https://www.cnblogs.com/Zinn/p/9248465.html
Copyright © 2011-2022 走看看