poj3728 商務旅行
[Description]
小 T 要經常進行商務旅行,他所在的國家有 N 個城鎮,標號為 1,2,3,...,N,這 N 個城鎮構
成一棵樹。每個城鎮可以買入和賣出貨物,同一城鎮買入和賣出的價格一樣,小 T 想從 a
走到 b,在這過程中,在某個城鎮買入一個貨物,然後在一個城鎮賣出,可以是同一城鎮買
入和賣出,使得收益最大,註意不能走回頭路。
[Input]
第一行一個數 N,第二行 N 個數,第 i 個數表示城鎮 i 買入和賣出貨物的價格。
接下來 N – 1 行,每行兩個數 a,b,表示 a 到 b 之間有一條雙向的道路。
接下一行一個數 Q,表示有 Q 個詢問,接下來 Q 行,每行兩個數 x,y,表示要求小 T 從 x
到 y 的最大收益。
[Output]
對於每個詢問,給出一個答案,各占一行。
[Sample Input]
10
16 5 1 15 15 1 8 9 9 15
1 2
1 3
2 4
2 5
2 6
6 7
4 8
1 9
1 10
6
9 1
5 1
1 7
3 3
1 1
3 6
[Sample Output]
7
11
7
0
0
15
[Hint]
對於 50%的數據,0 < n <= 1000,0 < m <= 100
對於 100%的數據,0 < n <= 100000,0 < m <= 10000,0 <= 貨物的價格 <= 10^8
設 fa[i][j]表示點 i 的第 2^j 個祖先
ma[i][j]表示點 i 到點 fa[i][j]的最大值。
mi[i][j]表示點 i 到點 fa[i][j]的最小值。
up[i][j]表示點 i 到點 fa[i][j]的最大獲利。
down[i][j]表示點 fa[i][j]到點 i 的最大獲利。
然後我們可以預處理出這四個數組。
即:
ma[x][i]=max(ma[fa[x][i-1]][i-1],ma[x][i-1]);
mi[x][i]=min(mi[fa[x][i-1]][i-1],mi[x][i-1]);
up[x][i]=max(max(up[fa[x][i-1]][i-1],up[x][i-1]),ma[fa[x][i-1]][i-1]-mi[x][i-1]);
down[x][i]=max(max(down[fa[x][i-1]][i-1],down[x][i-1]),ma[x][i-1]-mi[fa[x][i-1]][i-1]);
在走向最近公共祖先的路徑上記錄一下歷史最小值,在遠離最近公共祖先的路徑上記錄一下歷史最大值(在途中和最大獲利比較)。最後答案再和歷史最大值-歷史最小值比較一下即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 struct Node 7 { 8 int next,to; 9 }edge[300001]; 10 int head[100001],num,ans,dep[100001],val[100001],flag,n,Q; 11 int fa[100001][19],Min[100001][19],Max[100001][19],Up[100001][19],Down[100001][19]; 12 void add(int u,int v) 13 { 14 num++; 15 edge[num].next=head[u]; 16 head[u]=num; 17 edge[num].to=v; 18 } 19 void dfs(int x,int pa) 20 {int i; 21 if (dep[x]) return; 22 dep[x]=dep[pa]+1; 23 for (i=1;i<=18;i++) 24 { 25 fa[x][i]=fa[fa[x][i-1]][i-1]; 26 Max[x][i]=max(Max[x][i-1],Max[fa[x][i-1]][i-1]); 27 Min[x][i]=min(Min[x][i-1],Min[fa[x][i-1]][i-1]); 28 Up[x][i]=max(Up[x][i-1],Up[fa[x][i-1]][i-1]); 29 Up[x][i]=max(Up[x][i],Max[fa[x][i-1]][i-1]-Min[x][i-1]); 30 Down[x][i]=max(Down[x][i-1],Down[fa[x][i-1]][i-1]); 31 Down[x][i]=max(Down[x][i],Max[x][i-1]-Min[fa[x][i-1]][i-1]); 32 } 33 for (i=head[x];i;i=edge[i].next) 34 { 35 int v=edge[i].to; 36 if (v!=pa) 37 { 38 Max[v][0]=max(val[v],val[x]); 39 Min[v][0]=min(val[v],val[x]); 40 Up[v][0]=max(0,val[x]-val[v]); 41 Down[v][0]=max(0,val[v]-val[x]); 42 fa[v][0]=x; 43 dfs(v,x); 44 } 45 } 46 } 47 int LCA(int x,int y) 48 { 49 int i; 50 if (dep[x]<dep[y]) swap(x,y); 51 for (i=18;i>=0;i--) 52 if ((1<<i)<=dep[x]-dep[y]) 53 { 54 x=fa[x][i]; 55 } 56 if (x==y) 57 { 58 //cout<<"LCA:"<<‘ ‘<<x<<endl; 59 return x; 60 } 61 for (i=18;i>=0;i--) 62 if (fa[x][i]!=fa[y][i]) 63 { 64 x=fa[x][i]; 65 y=fa[y][i]; 66 } 67 x=fa[x][0]; 68 y=fa[y][0]; 69 //cout<<"LCA:"<<‘ ‘<<x<<endl; 70 return x; 71 } 72 void get_ans(int x,int y,int lca) 73 {int i; 74 int a=0,b=0,minv=2e9,maxv=0; 75 int small=2e9,large=0; 76 for (i=18;i>=0;i--) 77 if ((1<<i)<=dep[x]-dep[lca]) 78 { 79 b=max(b,Up[x][i]); 80 b=max(b,Max[x][i]-small); 81 small=min(small,Min[x][i]); 82 minv=min(minv,Min[x][i]); 83 x=fa[x][i]; 84 } 85 for (i=18;i>=0;i--) 86 if ((1<<i)<=dep[y]-dep[lca]) 87 { 88 a=max(a,Down[y][i]); 89 a=max(a,large-Min[y][i]); 90 large=max(large,Max[y][i]); 91 maxv=max(maxv,Max[y][i]); 92 y=fa[y][i]; 93 } 94 ans=max(a,max(b,maxv-minv)); 95 return; 96 } 97 int main() 98 {int i,u,v,x,y; 99 freopen("business.in","r",stdin); 100 freopen("business.out","w",stdout); 101 cin>>n; 102 memset(Min,127,sizeof(Min)); 103 for (i=1;i<=n;i++) 104 scanf("%d",&val[i]); 105 for (i=1;i<n;i++) 106 { 107 scanf("%d%d",&u,&v); 108 add(u,v);add(v,u); 109 } 110 dfs(1,0); 111 cin>>Q; 112 while (Q--) 113 { 114 scanf("%d%d",&x,&y); 115 if (x==y) printf("0\n"); 116 else 117 { 118 int lca=LCA(x,y); 119 get_ans(x,y,lca); 120 printf("%d\n",ans); 121 } 122 } 123 }
poj3728 商務旅行