1. 程式人生 > >cf 588E Duff in the Army 樹上倍增

cf 588E Duff in the Army 樹上倍增

pac 10個 ostream 倍增 stream 合並 amp 排列 告訴

題意概述:

給出一棵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 }

cf 588E Duff in the Army 樹上倍增