在线块状树LCA模板。
1 #include<cstdio> 2 #include<vector> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 #define N 30001 7 vector<int>G[N]; 8 typedef vector<int>::iterator ITER; 9 int dep[N],x,y,fa[N],top[N],siz[N],sz,n,m,ans; 10 int Abs(const int &x){return x<0?(-x):x;} 11 void makeblock(int U) 12 { 13 for(ITER it=G[U].begin();it!=G[U].end();it++) 14 if((*it)!=fa[U]) 15 { 16 fa[*it]=U; 17 dep[*it]=dep[U]+1; 18 if(siz[top[U]]<sz) 19 { 20 top[*it]=top[U]; 21 siz[top[U]]++; 22 } 23 makeblock(*it); 24 } 25 } 26 int lca(int U,int V) 27 { 28 while(U!=V) 29 { 30 if(top[U]!=top[V]) 31 { 32 if(dep[top[U]]<dep[top[V]]) swap(U,V); 33 U=fa[top[U]]; 34 } 35 else 36 { 37 if(dep[U]<dep[V]) swap(U,V); 38 U=fa[U]; 39 } 40 } 41 return U; 42 } 43 int main() 44 { 45 scanf("%d",&n); 46 for(int i=1;i<n;i++) 47 { 48 scanf("%d%d",&x,&y); 49 G[x].push_back(y); 50 G[y].push_back(x); 51 } sz=(int)sqrt((double)n); 52 for(int i=1;i<=n;i++) siz[i]=1,top[i]=i; 53 makeblock(1); scanf("%d%d",&m,&x); 54 for(int i=2;i<=m;i++) 55 { 56 scanf("%d",&y); int f=lca(x,y); 57 ans+=(dep[x]+dep[y]-(dep[f]<<1)); 58 x=y; 59 } 60 printf("%d ",ans); 61 return 0; 62 }