题意概述:
给出一棵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])的特判就可以做到不重不漏统计(之前都是用来求最值之类的所以没有注意到这个问题)。
然后还有为什么倍增数组第二维开成17省省空间在100000的时候wa了有哪位dalao可以告诉我。。。。
所以。。。数据结构是树的意思吗。。。。(感觉听了小火车讲课之后写代码的时候都在各种压长度?)
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][18],info[maxn][18][11],sz[maxn][18]; 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) c[l++]=a[i]<b[j]?a[i++]:b[j++]; 43 while(i<l1) c[l++]=a[i++]; 44 while(j<l2) c[l++]=b[j++]; 45 return min(l,10); 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,z,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 freopen("test.in","r",stdin); 94 freopen("test.out","w",stdout); 95 data_in(); 96 work(); 97 return 0; 98 }