倍增+归并树。
用我哥的说法,归并树就是把归并排序的结果记录下来然后乱搞。
实际上差不多就是这个意思。
其实就是每次求lca不断向上跳的时候更新答案。
然后其他都是倍增的板子,很板子。
其实这题拿到手我犹豫了,不知道写倍增还是写树剖,想想自己倍增要多复习就写了倍增。
然后惊奇地发现树剖是倍增码量的2~3倍。
所以考试还是首选倍增+归并树吧。

1 #include<cstdio> 2 #include<vector> 3 #define it register int 4 #define il inline 5 using namespace std; 6 const int N=400005; 7 int h[N],nxt[N],adj[N],w[N],n,m,Q,fa[N][20],u,v,t,x,d[N]; 8 vector<int> g[N][20],ans; 9 il void add(){ 10 nxt[++t]=h[u],h[u]=t,adj[t]=v,nxt[++t]=h[v],h[v]=t,adj[t]=u; 11 } 12 il int Min(it p,it q){ 13 return p<q?p:q; 14 } 15 il void fr(int &num){ 16 num=0;char c=getchar();int p=1; 17 while(c<'0'||c>'9') c=='-'?p=-1,c=getchar():c=getchar(); 18 while(c>='0'&&c<='9') num=num*10+c-'0',c=getchar(); 19 num*=p; 20 } 21 il vector<int> upd(vector<int>&a,vector<int>&b){ 22 vector<int> c; 23 c.clear(); 24 it i=0,j=0,sz1=a.size(),sz2=b.size(); 25 while(i<sz1&&j<sz2&&c.size()<10) a[i]<b[j]?c.push_back(a[i++]):c.push_back(b[j++]); 26 while(i<sz1&&c.size()<10) c.push_back(a[i++]); 27 while(j<sz2&&c.size()<10) c.push_back(b[j++]); 28 return c; 29 } 30 il void dfs(it x){ 31 d[x]=d[fa[x][0]]+1; 32 for(it i=h[x];i;i=nxt[i]) 33 if(adj[i]!=fa[x][0]) fa[adj[i]][0]=x,dfs(adj[i]); 34 } 35 il void sp(int &p,int &q){ 36 p+=q,q=p-q,p-=q; 37 } 38 il void lca(){ 39 ans.clear(); 40 if(d[u]<d[v]) sp(u,v); 41 it ds=d[u]-d[v]; 42 for(it i=17;i>=0;--i) 43 if(ds&(1<<i)) ans=upd(ans,g[u][i]),u=fa[u][i]; 44 if(u==v){ans=upd(ans,g[u][0]);return;} 45 for(it i=17;i>=0;--i) 46 if(fa[u][i]!=fa[v][i]) 47 ans=upd(ans,g[u][i]),ans=upd(ans,g[v][i]),u=fa[u][i],v=fa[v][i]; 48 ans=upd(ans,g[v][0]); 49 if(u!=v) ans=upd(ans,g[u][1]); 50 } 51 int main(){ 52 fr(n),fr(m),fr(Q); 53 for(it i=1;i<n;++i) fr(u),fr(v),add(); 54 for(it i=1;i<=m;++i) fr(x),g[x][0].push_back(i); 55 dfs(1); 56 for(it j=1;(1<<j)<=n;++j) 57 for(it i=1;i<=n;++i) 58 fa[i][j]=fa[fa[i][j-1]][j-1],g[i][j]=upd(g[i][j-1],g[fa[i][j-1]][j-1]); 59 while(Q--){ 60 fr(u),fr(v),fr(x),lca(); 61 it sz=Min(x,ans.size()); 62 printf("%d",sz); 63 for(it j=0;j<sz;++j) printf(" %d",ans[j]); 64 putchar(' '); 65 } 66 return 0; 67 }