zoukankan      html  css  js  c++  java
  • BZOJ 3282 Tree ——Link-Cut Tree

    【题目分析】

        明显的LCT维护连通性的题目。

        access的操作是比较巧妙的,可以把结点到根变成偏爱路径,而且保证了该点是链上深度最深的点。

        而且需边的思想也很巧妙,保证了复杂度。

        但是只能用于修改路径上的点的权值,不能用于修改整棵子树的信息。

        相比Splay,只能说是阉割了修改信息的作用,而增加了删边,加边的操作。

    【代码】

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
     
    #include <set>
    #include <map>
    #include <string>
    #include <algorithm>
    #include <vector>
    #include <iostream>
    #include <queue>
     
    using namespace std;
     
    #define maxn 1000005
    #define inf (0x3f3f3f3f)
     
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
     
    int ch[maxn][2],fa[maxn],num[maxn],xs[maxn],st[maxn],top=0,rev[maxn],n,m,sta[maxn];
     
    void update(int k)
    {xs[k]=num[k]^xs[ch[k][0]]^xs[ch[k][1]];}
     
    bool isroot(int k)
    {return ch[fa[k]][0]!=k&&ch[fa[k]][1]!=k;}
     
    void pushdown(int k)
    {
        if (rev[k])
        {
            rev[k]^=1;
            rev[ch[k][0]]^=1;
            rev[ch[k][1]]^=1;
            swap(ch[k][0],ch[k][1]);
        }
    }
     
    void rot(int x)
    {
        int y=fa[x],z=fa[y],l,r;
        if (ch[y][0]==x) l=0; else l=1;
        r=l^1;
        if (!isroot(y))
        {
            if (ch[z][0]==y) ch[z][0]=x;
            else ch[z][1]=x;
        }
        fa[x]=z; fa[y]=x; fa[ch[x][r]]=y;
        ch[y][l]=ch[x][r]; ch[x][r]=y;
        update(y); update(x);
    }
     
    void splay(int x)
    {
        top=0; sta[++top]=x;
        for (int i=x;!isroot(i);i=fa[i]) sta[++top]=fa[i];
        while (top) pushdown(sta[top--]);
        while (!isroot(x))
        {
            int y=fa[x],z=fa[y];
            if (!isroot(y))
            {
                if (ch[y][0]==x^ch[z][0]==y) rot(y);
                else rot(x);
            }
            rot(x);
        }
    }
     
    void access(int x)
    {
        for (int t=0;x;t=x,x=fa[x])
            splay(x),ch[x][1]=t,update(x);
    }
     
    void makeroot(int x)
    {
        access(x); splay(x); rev[x]^=1;
    }
     
    int find(int x)
    {
        access(x);
        splay(x);
        while (ch[x][0]) x=ch[x][0];
        return x;
    }
     
    void cut(int x,int y)
    {
        makeroot(x);
        access(y);
        splay(y);
        if (ch[y][0]==x) ch[y][0]=fa[x]=0;
    }
     
    void link(int x,int y)
    {
        makeroot(x);
        fa[x]=y;
    }
     
    int main()
    {
        n=read(); m=read();
        for (int i=1;i<=n;++i) xs[i]=num[i]=read();
        int opt,x,y;
        while (m--)
        {
            opt=read();x=read();y=read();
            switch (opt)
            {
                case 0:makeroot(x); access(y); splay(y); printf("%d
    ",xs[y]); break;
                case 1:if (find(x)!=find(y)) link(x,y); break;
                case 2:if (find(x)==find(y)) cut(x,y); break;
                case 3:access(x); splay(x); num[x]=y; update(x); break;
            }
        }
    }
    

      

  • 相关阅读:
    jsp有哪些内置对象?作用分别是什么?
    Servlet API中forward()与redirect()的区别?
    jsp和servlet的区别、共同点、各自应用的范围?
    Servlet的生命周期
    如何从CDN加载jQuery?
    什么是CDN?哪些是流行的jQuery CDN?使用CDN有什么好处?
    window.onload()函数和jQuery中的document.ready()有什么区别?
    jquery中$.get()提交和$.post()提交有区别吗?
    .JQuery有几种选择器?
    如何在JavaScript中每x秒调用一个函数
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6195056.html
Copyright © 2011-2022 走看看