1. 程式人生 > >[BJOI2014] 大融合

[BJOI2014] 大融合

pushd swa 連接 clu org 是把 pre sin return

一道不怎麽裸的LCT。

題目傳送門(洛谷P4219)

這道題明顯是詢問一條邊所連接的兩個連通塊的大小之積。

LCT怎麽維護子樹大小呢?

推薦一個大佬的博客(傳送門):大佬的這篇博客有詳解也有題,真心很棒的。

回到LCT,維護子樹信息的話,我的理解就是把虛子樹的信息也記錄下來。

更新子樹信息的時候把虛子樹的也加進去。

至於怎麽維護虛子樹信息:

access和link的時候改變了樹的形態,所以要順便更新一下虛子樹的信息。

access的時候是失去一個虛兒子又得到一個虛兒子。

link的時候連完邊就順手更新了。

別的操作沒改變樹的形態,所以虛子樹信息不會變,代碼跟原來一模一樣的。

所以這道題現在就基本上也是裸題啦。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define id(x) (s[f[x]][1]==x)
  5 using namespace std;
  6 
  7 int n,m;
  8 int s[100005][2],f[100005],szi[100005],sz[100005];
  9 bool rt[100005],rev[100005];
 10 
 11 void pushup(int p)
 12 {
 13     sz[p]=sz[s[p][0]]+sz[s[p][1]]+szi[p]+1
; 14 } 15 16 void reverse(int p) 17 { 18 swap(s[p][0],s[p][1]); 19 rev[p]^=1; 20 } 21 22 void pushdown(int p) 23 { 24 if(!rev[p])return; 25 reverse(s[p][0]); 26 reverse(s[p][1]); 27 rev[p]=0; 28 } 29 30 void down(int p) 31 { 32 if(!rt[p])down(f[p]); 33 pushdown(p);
34 } 35 36 void rotate(int p) 37 { 38 int k=id(p); 39 int fa=f[p]; 40 if(rt[fa])rt[p]=1,rt[fa]=0; 41 else s[f[fa]][id(fa)]=p; 42 s[fa][k]=s[p][!k]; 43 s[p][!k]=fa; 44 f[p]=f[fa]; 45 f[fa]=p; 46 f[s[fa][k]]=fa; 47 pushup(fa); 48 pushup(p); 49 } 50 51 void splay(int p) 52 { 53 down(p); 54 while(!rt[p]) 55 { 56 int fa=f[p]; 57 if(rt[fa]) 58 { 59 rotate(p); 60 return; 61 } 62 if(id(p)^id(fa))rotate(p); 63 else rotate(fa); 64 rotate(p); 65 } 66 } 67 68 void access(int p) 69 { 70 int son=0; 71 while(p) 72 { 73 splay(p); 74 szi[p]+=sz[s[p][1]]; 75 rt[s[p][1]]=1,rt[son]=0; 76 s[p][1]=son; 77 szi[p]-=sz[s[p][1]]; 78 pushup(p); 79 son=p,p=f[p]; 80 } 81 } 82 83 void mtr(int p) 84 { 85 access(p); 86 splay(p); 87 reverse(p); 88 } 89 90 void seperate(int x,int y) 91 { 92 mtr(x); 93 access(y); 94 splay(y); 95 } 96 97 int main() 98 { 99 scanf("%d%d",&n,&m); 100 for(int i=1;i<=n;i++)sz[i]=rt[i]=1; 101 for(int i=1;i<=m;i++) 102 { 103 char op[5]; 104 scanf("%s",op+1); 105 int x,y; 106 scanf("%d%d",&x,&y); 107 if(op[1]==A) 108 { 109 seperate(x,y); 110 f[x]=y; 111 szi[y]+=sz[x]; 112 pushup(y); 113 } 114 if(op[1]==Q) 115 { 116 seperate(x,y); 117 printf("%lld\n",(long long)(szi[x]+1)*(szi[y]+1)); 118 } 119 } 120 return 0; 121 }

[BJOI2014] 大融合