题解CF587C Duff in the Army

题目:CF587C Duff in the Army

倍增+归并树。

用我哥的说法,归并树就是把归并排序的结果记录下来然后乱搞。

实际上差不多就是这个意思。

其实就是每次求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('\n');
65     } 
66     return 0;
67 }
View Code

 

posted @ 2019-10-11 15:46  kylin_xy  阅读(139)  评论(0编辑  收藏  举报