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 }

 

posted @ 2017-10-13 17:20  Z-Y-Y-S  阅读(405)  评论(0编辑  收藏  举报