[HNOI2016]樹
Description
小A想做一棵很大的樹,但是他手上的材料有限,只好用點小技巧了。開始,小A只有一棵結點數為N的樹,結
點的編號為1,2,…,N,其中結點1為根;我們稱這顆樹為模板樹。小A決定通過這棵模板樹來構建一顆大樹。構建過
程如下:(1)將模板樹復制為初始的大樹。(2)以下(2.1)(2.2)(2.3)步循環執行M次(2.1)選擇兩個數字a,b,
其中1<=a<=N,1<=b<=當前大樹的結點數。(2.2)將模板樹中以結點a為根的子樹復制一遍,掛到大樹中結點b的下
方(也就是說,模板樹中的結點a為根的子樹復制到大樹中後,將成為大樹中結點b的子樹)。(2.3)將新加入大樹
樹共有C個結點,那麽新加入模板樹的C個結點在大樹中的編號將是L+1,L+2,…,L+C;大樹中這C個結點編號的大小
順序和模板樹中對應的C個結點的大小順序是一致的。下面給出一個實例。假設模板樹如下圖:
根據第(1)步,初始的大樹與模板樹是相同的。在(2.1)步,假設選擇了a=4,b=3。運行(2.2)和(2.3)後,得到新的
大樹如下圖所示
現在他想問你,樹中一些結點對的距離是多少。
Input
第一行三個整數:N,M,Q,以空格隔開,N表示模板樹結點數,M表示第(2)中的循環操作的次數,Q 表示詢問數
板樹中 x 為根的子樹復制到大樹中成為結點to的子樹的一次操作。再接下來Q行,每行兩個整數fr,to,表示詢問
大樹中結點 fr和 to之間的距離是多少。N,M,Q<=100000
Output
輸出Q行,每行一個整數,第 i行是第 i個詢問的答案。
Sample Input
5 2 31 4
1 3
4 2
4 5
4 3
3 2
6 9
1 8
5 3
Sample Output
63
3
HINT
經過兩次操作後,大樹變成了下圖所示的形狀:
結點6到9之間經過了6條邊,所以距離為6;類似地,結點1到8之間經過了3條邊;結點5到3之間也經過了3條邊。
如果看不懂可以看一下下面幾個博客
http://www.cnblogs.com/wfj2048/p/6416591.html
把每一個新添的子樹縮成一個點,那麽新樹就只有m+1點(模板樹算一個點)
每一次加樹就等於鏈接新樹中兩個點
判斷y在哪個點用二分,鏈接的邊權為兩個點代表的子樹根節點的距離
判斷這個新點連上的點對應模板樹的哪個點,需要判斷dfs序區間內的區間第k大,這要用到主席樹
查詢(x,y)時分清況:先求出(x,y)在模板樹的對應點(u,v),新樹上的w=LCA(p,q)
1.兩個屬同一個子樹,在模板樹求(u,v)距離
2.不屬於同一子樹(p,q),先求出在新樹上的距離,再加上u->u的子樹根的距離(模板樹),v同理
因為這樣算出的距離在w的子樹中可能多算,因為路徑不一定經過w的根
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 typedef long long lol; 8 struct ZYYS 9 { 10 lol rt,id,pre; 11 lol l,r; 12 }a[100005]; 13 lol pos,ch[6000005][2],sum[6000005],n,m,root[100005]; 14 lol ans; 15 struct Tree 16 { 17 struct Node 18 { 19 lol next,to; 20 lol dis; 21 }edge[200005]; 22 lol head[100005],num,dep[100005],size[100005],id[100005],lx[100005],rx[100005],top[100005],cnt,son[100005],fa[100005]; 23 lol d[100005]; 24 void add(lol u,lol v,lol dis) 25 { 26 num++; 27 edge[num].next=head[u]; 28 head[u]=num; 29 edge[num].to=v; 30 edge[num].dis=dis; 31 } 32 void dfs1(lol x,lol pa) 33 {lol i; 34 dep[x]=dep[pa]+1; 35 size[x]=1; 36 fa[x]=pa; 37 for (i=head[x];i;i=edge[i].next) 38 { 39 lol v=edge[i].to; 40 if (v!=pa) 41 { 42 d[v]=d[x]+edge[i].dis; 43 dfs1(v,x); 44 size[x]+=size[v]; 45 if (size[v]>size[son[x]]) son[x]=v; 46 } 47 } 48 } 49 void dfs2(lol x,lol pa,lol tp) 50 {lol i; 51 lx[x]=++cnt; 52 id[cnt]=x; 53 top[x]=tp; 54 if (son[x]) 55 { 56 dfs2(son[x],x,tp); 57 } 58 for (i=head[x];i;i=edge[i].next) 59 { 60 lol v=edge[i].to; 61 if (v==pa||v==son[x]) continue; 62 dfs2(v,x,v); 63 } 64 rx[x]=cnt; 65 } 66 lol gettop(lol x,lol y) 67 {lol z; 68 while (top[x]!=top[y]) 69 { 70 z=top[x]; 71 x=fa[top[x]]; 72 } 73 if (x==y) return z; 74 return son[y]; 75 } 76 lol lca(lol x,lol y) 77 { 78 while (top[x]!=top[y]) 79 { 80 if (dep[top[x]]<dep[top[y]]) swap(x,y); 81 x=fa[top[x]]; 82 } 83 if (dep[x]>dep[y]) swap(x,y); 84 return x; 85 } 86 lol dist(lol x,lol y) 87 { 88 return d[x]+d[y]-2*d[lca(x,y)]; 89 } 90 }t1,t2; 91 lol getid(lol k,lol r) 92 { 93 lol l=1,as=0; 94 while (l<=r) 95 { 96 lol mid=(l+r)/2; 97 if (a[mid].l<=k) as=mid,l=mid+1; 98 else r=mid-1; 99 } 100 return as; 101 } 102 void update(lol x,lol &y,lol l,lol r,lol k) 103 { 104 y=++pos; 105 ch[y][0]=ch[x][0];ch[y][1]=ch[x][1]; 106 sum[y]=sum[x]+1; 107 if (l==r) return; 108 lol mid=(l+r)/2; 109 if (k<=mid) update(ch[x][0],ch[y][0],l,mid,k); 110 else update(ch[x][1],ch[y][1],mid+1,r,k); 111 } 112 lol query(lol x,lol y,lol l,lol r,lol k) 113 { 114 if (l==r) return l; 115 lol mid=(l+r)/2; 116 lol zyys=sum[ch[y][0]]-sum[ch[x][0]]; 117 if (zyys<k) return query(ch[x][1],ch[y][1],mid+1,r,k-zyys); 118 else return query(ch[x][0],ch[y][0],l,mid,k); 119 } 120 int main() 121 {lol i,Q; 122 lol x,y,u,v; 123 cin>>n>>m>>Q; 124 for (i=1;i<=n-1;i++) 125 { 126 scanf("%lld%lld",&u,&v); 127 t1.add(u,v,1); 128 t1.add(v,u,1); 129 } 130 t1.dfs1(1,0); 131 t1.dfs2(1,0,1); 132 for (i=1;i<=n;i++) 133 update(root[i-1],root[i],1,n,t1.id[i]); 134 a[1].id=1;a[1].rt=1;a[1].l=1;a[1].r=n; 135 for (i=1;i<=m;i++) 136 { 137 scanf("%lld%lld",&x,&y); 138 a[i+1].id=i+1;a[i+1].rt=x; 139 a[i+1].l=a[i].r+1; 140 a[i+1].r=a[i+1].l+t1.size[x]-1; 141 lol z=getid(y,i); 142 a[i+1].pre=y=query(root[t1.lx[a[z].rt]-1],root[t1.rx[a[z].rt]],1,n,y-a[z].l+1); 143 t2.add(z,i+1,t1.d[y]-t1.d[a[z].rt]+1); 144 t2.add(i+1,z,t1.d[y]-t1.d[a[z].rt]+1); 145 } 146 t2.dfs1(1,0);t2.dfs2(1,0,1); 147 for (i=1;i<=Q;i++) 148 { 149 scanf("%lld%lld",&x,&y); 150 lol p=getid(x,m+1),q=getid(y,m+1); 151 lol w=t2.lca(p,q); 152 lol u=query(root[t1.lx[a[p].rt]-1],root[t1.rx[a[p].rt]],1,n,x-a[p].l+1); 153 lol v=query(root[t1.lx[a[q].rt]-1],root[t1.rx[a[q].rt]],1,n,y-a[q].l+1); 154 if (p==q) 155 { 156 printf("%lld\n",t1.dist(u,v)); 157 } 158 else 159 { 160 if (p==w) swap(p,q),swap(u,v); 161 if (q==w) 162 { 163 x=t2.gettop(p,w); 164 ans=t2.d[p]-t2.d[x]+t1.d[u]-t1.d[a[p].rt]; 165 u=a[x].pre; 166 ans+=t1.dist(u,v)+1; 167 } 168 else 169 { 170 ans=(t1.d[u]-t1.d[a[p].rt]+t1.d[v]-t1.d[a[q].rt]); 171 ans+=t2.dist(p,q); 172 x=t2.gettop(p,w);y=t2.gettop(q,w); 173 u=a[x].pre;v=a[y].pre; 174 ans+=(t1.d[a[w].rt]-t1.d[t1.lca(u,v)])*2; 175 } 176 printf("%lld\n",ans); 177 } 178 } 179 }
[HNOI2016]樹