1. 程式人生 > >poj3728 商務旅行

poj3728 商務旅行

input 數組 int 預處理 log iostream 之間 兩個 sca

[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 商務旅行