zoukankan      html  css  js  c++  java
  • bzoj 4530 [Bjoi2014]大融合——LCT维护子树信息

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4530

    LCT维护子树 siz 。设 sm[ ] 表示轻儿子的 siz 和+1(1是自己的siz),siz[ ] 表示 splay 里 ( 两个儿子的 siz[ ] ) + sm[ cr ] 。在 access 里随便维护一下就好了。

    一开始写的 siz[ ]  是 splay 里右儿子的 siz[ ] + sm[ cr ] ,但打 rev[ ]  的时候难以维护,所以弃了。

    注意要先让一个点作为 splay 的根,再给它连右儿子,才能比较好地维护好;所以 link( ) 的时候注意 access( y ) !

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    using namespace std;
    const int N=1e5+5;
    int n,Q,fa[N],c[N][2],siz[N],sm[N];
    int sta[N],top;bool rev[N];
    int rdn()
    {
      int ret=0;bool fx=1;char ch=getchar();
      while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return fx?ret:-ret;
    }
    bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
    void pshp(int x){siz[x]=sm[x]+siz[c[x][0]]+siz[c[x][1]];}
    void Rev(int x)
    {
      if(!rev[x])return;rev[x]=0;
      rev[c[x][0]]^=1;rev[c[x][1]]^=1;
      swap(c[x][0],c[x][1]);
    }
    void rotate(int x)
    {
      int y=fa[x],z=fa[y],d=(x==c[y][1]);
      if(!isroot(y))c[z][y==c[z][1]]=x;
      fa[x]=z;
      fa[y]=x;fa[c[x][!d]]=y;
      c[y][d]=c[x][!d];c[x][!d]=y;
      pshp(y);pshp(x);
    }
    void splay(int x)
    {
      sta[top=1]=x;
      for(int k=x;!isroot(k);k=fa[k])sta[++top]=fa[k];
      for(int i=top;i;i--)Rev(sta[i]);
      int y,z;
      while(!isroot(x))
        {
          y=fa[x];z=fa[y];
          if(!isroot(y))
        ((x==c[y][0])^(y==c[z][0]))?rotate(x):rotate(y);
          rotate(x);
        }
    }
    void access(int x)
    {
      int t=0;
      while(x)
        {
          splay(x);
          sm[x]+=siz[c[x][1]];
          sm[x]-=siz[t];
          c[x][1]=t;
          pshp(x);/////
          t=x;x=fa[x];
        }
    }
    void makeroot(int x)
    {
      access(x);splay(x);rev[x]^=1;
    }
    void link(int x,int y)
    {
      makeroot(x);access(y);splay(y);//access()!!!
      fa[x]=y;sm[y]+=siz[x];siz[y]+=siz[x];
    }
    ll query(int x,int y)
    {
      makeroot(x);access(y);splay(y);
      return (ll)siz[x]*sm[y];
    }
    int main()
    {
      n=rdn();Q=rdn();
      for(int i=1;i<=n;i++)siz[i]=1,sm[i]=1;
      int x,y;char ch[3];
      while(Q--)
        {
          scanf("%s",ch);x=rdn();y=rdn();
          if(ch[0]=='A')link(x,y);
          else printf("%lld
    ",query(x,y));
        }
      return 0;
    }
  • 相关阅读:
    java常用设计模式链接
    常用设计模式汇总
    转:面试的角度诠释Java工程师(二)
    转:面试的角度诠释Java工程师(一)
    神经网络与深度学习_邱锡鹏——无监督学习和信息论
    智能推荐算法在直播场景中的应用
    经纬度地点之间距离测算
    <3>Transformer 到bert 模型
    <4>从bert到XLnet
    <2>自然语言难在哪? ----刘知远教授
  • 原文地址:https://www.cnblogs.com/Narh/p/10140314.html
Copyright © 2011-2022 走看看