bzoj4530[Bjoi2014]大融合 LCT维护子树信息
Posted yinwuxiao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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; }
以上是关于bzoj4530[Bjoi2014]大融合 LCT维护子树信息的主要内容,如果未能解决你的问题,请参考以下文章