Codeforces Round #326 Div.1 C.Duff in the Army 树上倍增
题意概述:
给出一棵N个结点的树,然后有M个居民分散在这棵树的结点上(允许某个结点没有居民)。现在给出一些询问形如u,v,a,定义k=min(x,a),其中x表示的是u->v路径上的居民数量。将所有路径上的居民编号升序排列之后得到序列p1,p2,...,px,要求对于每一组询问,输出k,p1,p2,...,pk。
N,M,Q<=10^5,1<=a<=10.
分析:
实际上这个题是被丢在数据结构作业里面的只是。。。。好像没有这个必要?
分析一波可以发现每个点可能在答案中出现的居民最多只有10个,所以说按照出现的顺序依次把每个点的至多10个居民储存起来,然后倍增的时候用归并排序的思想合并就可以了。时间复杂度O(10nlogn)。
实现过程中注意到一些问题,今后用倍增统计点的信息的时候都用半开半闭就好了,加上对链顶端(x=y时对x,否则x,y一起爬之后对x,y,fa[x][0])的特判就可以做到不重不漏统计(之前都是用来求最值之类的所以没有注意到这个问题)。
所以。。。数据结构是树的意思吗。。。。(感觉听了小火车讲课之后写代码的时候都在各种压长度?)
所以这个时限的4s是输入输出的锅?(实测手写0.5s的事情)
1 #include<iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<cstdlib>
5 #include<algorithm>
6 #include<cmath>
7 #include<queue>
8 #include<set>
9 #include<map>
10 #include<vector>
11 #include<cctype>
12 using namespace std;
13 const int maxn=100005;
14
15 int N,M,Q;
16 struct edge{ int to,next; }E[maxn<<1];
17 int first[maxn],np,dep[maxn],fa[maxn][17],info[maxn][17][10],sz[maxn][17];
18 int ans[25],tmp[25];
19
20 void add_edge(int u,int v)
21 {
22 E[++np]=(edge){v,first[u]};
23 first[u]=np;
24 }
25 void data_in()
26 {
27 scanf("%d%d%d",&N,&M,&Q);
28 int x,y;
29 for(int i=1;i<N;i++){
30 scanf("%d%d",&x,&y);
31 add_edge(x,y);
32 add_edge(y,x);
33 }
34 for(int i=1;i<=M;i++){
35 scanf("%d",&x);
36 if(sz[x][0]<10) info[x][0][sz[x][0]++]=i;
37 }
38 }
39 int merge(int *a,int *b,int l1,int l2,int *c)
40 {
41 int l=0,i=0,j=0;
42 while(i<l1&&j<l2&&l<10) c[l++]=a[i]<b[j]?a[i++]:b[j++];
43 while(i<l1&&l<10) c[l++]=a[i++];
44 while(j<l2&&l<10) c[l++]=b[j++];
45 return l;
46 }
47 void DFS(int i,int f,int d)
48 {
49 fa[i][0]=f,dep[i]=d;
50 for(int j=1;(1<<j)<d;j++){
51 fa[i][j]=fa[fa[i][j-1]][j-1];
52 sz[i][j]=merge(info[i][j-1],info[fa[i][j-1]][j-1],sz[i][j-1],sz[fa[i][j-1]][j-1],info[i][j]);
53 }
54 for(int p=first[i];p;p=E[p].next){
55 int j=E[p].to;
56 if(j==f) continue;
57 DFS(j,i,d+1);
58 }
59 }
60 void cc(int *n,int &l,int x,int i)
61 {
62 l=merge(n,info[x][i],l,sz[x][i],tmp);
63 for(int k=0;k<l;k++) n[k]=tmp[k];
64 }
65 void LCA(int x,int y,int *n,int &l)
66 {
67 if(dep[x]<dep[y]) swap(x,y);
68 int len=dep[x]-dep[y]; l=0;
69 for(int i=0;(1<<i)<=len;i++)
70 if((1<<i)&len){ cc(n,l,x,i); x=fa[x][i]; }
71 if(x==y){ cc(n,l,x,0); return; }
72 for(int i=16;i>=0;i--) if(fa[x][i]!=fa[y][i]){
73 cc(n,l,x,i); cc(n,l,y,i);
74 x=fa[x][i],y=fa[y][i];
75 }
76 cc(n,l,x,0); cc(n,l,y,0);
77 cc(n,l,fa[x][0],0);
78 }
79 void work()
80 {
81 DFS(1,0,1);
82 int x,y,a,l;
83 for(int i=1;i<=Q;i++){
84 scanf("%d%d%d",&x,&y,&a);
85 LCA(x,y,ans,l);
86 printf("%d ",min(a,l));
87 for(int j=0;j<min(a,l);j++) printf("%d ",ans[j]);
88 printf("\n");
89 }
90 }
91 int main()
92 {
93 data_in();
94 work();
95 return 0;
96 }