【bzoj4530】[Bjoi2014]大融合 LCT维护子树信息

题解:

lct维护子树信息

推荐https://www.cnblogs.com/GXZlegend/p/7061458.html,非常详细

总的来说就是 维护虚树信息和子树信息

虚树信息只有在access和link时才会改变

下面是对拍程序

my

#include <bits/stdc++.h>
using namespace std;
char cc;
int x,y,n,m;
#define N 200000
int count2[N],count3[N],ls[N],rs[N],fa[N];
bool rev[N];
void updata(int x)
{
  count2[x]=count3[x]+count2[ls[x]]+count2[rs[x]]+1;
}
void down(int x)
{
  if (!rev[x]) return;
  swap(ls[x],rs[x]);
  rev[ls[x]]^=1; rev[rs[x]]^=1;
  rev[x]=0;
}
bool pd(int x)
{
  int y=fa[x];
  if (ls[y]!=x&&rs[y]!=x) return(0);
  else return(1);
}
void rotate(int x,int y)
{
  int ft=fa[x];
  if (y==1)
  {
    rs[ft]=ls[x];
    if (ls[x]) fa[ls[x]]=ft;
  } else
  {
    ls[ft]=rs[x];
    if (rs[x]) fa[rs[x]]=ft;
  }
  fa[x]=fa[ft];
  if (pd(ft))
  {
    if (ls[fa[ft]]==ft) ls[fa[ft]]=x;
    else rs[fa[ft]]=x;
  }
  fa[ft]=x;
  if (y==1) ls[x]=ft; else rs[x]=ft;
  updata(ft); updata(x);
}
void dfs(int x)
{
  if (pd(x)) dfs(fa[x]);
  down(x);
}
void splay(int x)
{
  dfs(x);
  int ft=fa[x];
  while (pd(x))
  {
    if (!pd(ft))
    {
      if (x==ls[ft]) rotate(x,2);
      else rotate(x,1);
    } else
    {
      if (ft==ls[fa[ft]])
      {
        if (x==ls[ft])
          rotate(ft,2),rotate(x,2);
        else rotate(x,1),rotate(x,2); 
      } else
      {
        if (x==rs[ft])
          rotate(ft,1),rotate(x,1);
        else rotate(x,2),rotate(x,1);
      }
    }
    ft=fa[x];
  }
}
void access(int x)
{
  for (int y=0;x;y=x,x=fa[x])
    splay(x),count3[x]+=count2[rs[x]]-count2[y]
    ,rs[x]=y,updata(x);
}
void makeroot(int x)
{
   access(x);
   splay(x);
   rev[x]^=1;
}
int findroot(int x)
{
   access(x);
   splay(x);
   while (ls[x]) x=ls[x];
   return x;
}
void split(int x,int y)
{
  makeroot(x);
  access(y);
  splay(y);
}
void link(int x,int y)
{
  makeroot(x);
  if (findroot(y)!=x)
  { 
    fa[x]=y;
    count3[y]+=count2[x];
    updata(y);
  }
}
int main()
{
  freopen("noip.in","r",stdin);
  freopen("noip.out","w",stdout);
  std::ios::sync_with_stdio(false);
  cin>>n>>m;
  for (int i=1;i<=m;i++)
  {
    cin>>cc>>x>>y;
    if (cc=='A')
    {
      link(x,y);
    } else
    {
      split(x,y);
      int tmp=count2[x];
      split(y,x);
      tmp*=count2[y];
      cout<<tmp<<endl;
    }
  }
  return 0;
}

maker

#include <bits/stdc++.h>
using namespace std;
int fa[100000];
bool f[1010][1010];
int find(int x)
{
  if (fa[x]!=x) return(find(fa[x]));
  else return(x);
}
int main()
{
  freopen("noip.in","w",stdout);
  int n=1000,m=800;
  srand(time(0));
  cout<<n<<" "<<m<<endl;
  for (int i=1;i<=n;i++) fa[i]=i;
  for (int i=1;i<=600;i++)
  {
    while (1)
    {
      int x=rand()%n+1,y=rand()%n+1;
      if (find(x)!=find(y))
      {
        f[x][y]=1; f[y][x]=1;
        fa[find(x)]=find(y);
        cout<<"A "<<x<<" "<<y<<endl;
        break;
      }
    }
  }
  for (int i=1;i<=200;i++)
  {
    while (1)
    {
      int x=rand()%n+1,y=rand()%n+1;
      if (f[x][y])
      {
        cout<<"Q "<<x<<" "<<y<<endl;
        break;
      }
    }
  }
  return 0;
} 

dp

#include <cstdio>
#include <algorithm>
#define N 100010
using namespace std;
int fa[N] , c[2][N] , si[N] , sum[N] , rev[N];
char str[5];
void pushup(int x)
{
    sum[x] = sum[c[0][x]] + sum[c[1][x]] + si[x] + 1;
}
void pushdown(int x)
{
    if(rev[x])
    {
        int l = c[0][x] , r = c[1][x];
        swap(c[0][l] , c[1][l]) , swap(c[0][r] , c[1][r]);
        rev[l] ^= 1 , rev[r] ^= 1 , rev[x] = 0;
    }
}
bool isroot(int x)
{
    return c[0][fa[x]] != x && c[1][fa[x]] != x;
}
void update(int x)
{
    if(!isroot(x)) update(fa[x]);
    pushdown(x);
}
void rotate(int x)
{
    int y = fa[x] , z = fa[y] , l = (c[1][y] == x) , r = l ^ 1;
    if(!isroot(y)) c[c[1][z] == y][z] = x;
    fa[x] = z , fa[y] = x , fa[c[r][x]] = y , c[l][y] = c[r][x] , c[r][x] = y;
    pushup(y) , pushup(x);
}
void splay(int x)
{
    update(x);
    while(!isroot(x))
    {
        int y = fa[x] , z = fa[y];
        if(!isroot(y))
        {
            if((c[0][y] == x) ^ (c[0][z] == y)) rotate(x);
            else rotate(y);
        }
        rotate(x);
    }
}
void access(int x)
{
    int t = 0;
    while(x) splay(x) , si[x] += sum[c[0][x]] - sum[t] , c[0][x] = t , pushup(x) , t = x , x = fa[x];
}
void makeroot(int x)
{
    access(x) , splay(x) , swap(c[0][x] , c[1][x]) , rev[x] = 1;
}
void split(int x , int y)
{
    makeroot(x) , makeroot(y);
}
void link(int x , int y)
{
    split(x , y) , fa[x] = y , si[y] += sum[x] , pushup(y);
}
int main()
{
  freopen("noip.in","r",stdin);
  freopen("noip2.out","w",stdout);
    int n , m , i , x , y;
    scanf("%d%d" , &n , &m);
    for(i = 1 ; i <= n ; i ++ ) sum[i] = 1;
    while(m -- )
    {
        scanf("%s%d%d" , str , &x , &y);
        if(str[0] == 'A') link(x , y);
        else split(x , y) , printf("%lld\n" , (long long)sum[x] * (sum[y] - sum[x]));
    }
    return 0;
}

 

posted @ 2018-04-08 22:48  尹吴潇  阅读(138)  评论(0编辑  收藏  举报