poj3728 The merchant

题目:The merchant

题目描述:给出一棵有n个带权(price)节点的树(结点数n<=50000),给出m组询问{v,u},询问从v到u中差最多是多少(询问次数m<=50000)。

分析:

  (1)算法一:最朴素的方法是从v到u完整的访问一遍,枚举一个在{v,u}这条路径上的点o作为卖出点x,求出{v,o}这条路的最小值y作为买入点,{x-y}的最大值即为所求结果。

  (2)分析算法一:对于{v,o}这条路的最小值y,要使得{y-x}最大,那x必然是{o.u}的最大值。{v,u}中的差必然是{v,o}的差、{o,u}的差、{o.u}的最大值-{v,o}的最小值中取最大值。可以采取分治算法。

  (3)算法二:把{v,u}的最近公共祖先lca最作为o分治算法的分割点。{v,u}中的差是{v,lca}的差、{lca,u}的差、{lca.u}的最大值-{v,lca}的最小值中取最大值。问题转化为快速计算{v,lca}的差,{lca,u}的差,{lca,u}的最大值,{v,lca}的最小值,仍然采用分治思想,利用倍增进行预处理和加速计算。

  (4)算法三:由于询问没有相关性,而且所有询问在一开始就已经知道,可以离线计算。采用Tarjan算法,用并查集维护{v,lca}的差,{lca,u}的差,{lca,u}的最大值,{v,lca}的最小值。

  (5)算法二和算法三均利用了分析二的思路。

  (6)扩展:问题中的树如果退化成一条链,有其他做法。用一个新序列$w_2-w_1,w_3-w_2 ,cdots, w_n-w_{n-1}$,这样只需要求得询问区间最大子段和即为结果Max-Min了,可以采用线段树去加速计算,做法类似{USACO 2008 Feb Hotel}一题。

代码:

算法二:

 1 #include <cstdio>
 2 #include <algorithm>
 3 const int Inf=1e9;
 4 int Tval[50005],Tdep[50005],Tfa[50005][21];
 5 int Tmin[50005][21],Tmax[50005][21],Tup[50005][21],Tdown[50005][21];
 6 int size,first[50005];
 7 struct Edge{int to,next;}e[100005];
 8 int Read(){
 9     int ch='@',t=0;
10     for(;ch<48 || 57<ch;ch=getchar());
11     for(;47<ch && ch<58;ch=getchar())t=t*10+ch-48;
12     return t;
13 } 
14 inline int max(int x,int y) {x-=y;return y+(x&(~(x>>31)));}
15 inline int min(int x,int y) {x-=y;return y+(x&(x>>31));}
16 void addedge(int x,int y){
17     e[++size].to=y;e[size].next=first[x];first[x]=size;
18     e[++size].to=x;e[size].next=first[y];first[y]=size;
19 }
20 void LcaInit(int v){
21     for(int i=1,j,k,tv;i<17;++i){
22         Tfa[v][i]=Tfa[Tfa[v][i-1]][i-1];
23         Tmin[v][i]=min(Tmin[v][i-1],Tmin[Tfa[v][i-1]][i-1]);
24         Tmax[v][i]=max(Tmax[v][i-1],Tmax[Tfa[v][i-1]][i-1]);
25         Tup[v][i]=max(max(Tup[v][i-1],Tup[Tfa[v][i-1]][i-1]),Tmax[Tfa[v][i-1]][i-1]-Tmin[v][i-1]);
26         Tdown[v][i]=max(max(Tdown[v][i-1],Tdown[Tfa[v][i-1]][i-1]),Tmax[v][i-1]-Tmin[Tfa[v][i-1]][i-1]);
27     }
28     for(int i=first[v],u;i;i=e[i].next){
29         u=e[i].to;if(u==Tfa[v][0])continue;
30         Tfa[u][0]=v;
31         Tdep[u]=Tdep[v]+1;
32         Tmin[u][0]=min(Tval[u],Tval[v]);
33         Tmax[u][0]=max(Tval[u],Tval[v]);
34         Tup[u][0]=max(0,Tval[v]-Tval[u]);
35         Tdown[u][0]=max(0,Tval[u]-Tval[v]);
36         LcaInit(u);
37     }
38 }
39 int GetLca(int v,int u){
40     if(Tdep[v]<Tdep[u])std::swap(v,u);
41     for(int i=16;i>=0;--i)
42         if((Tdep[v]-Tdep[u])&(1<<i))v=Tfa[v][i];
43     if(v==u)return v;
44     for(int i=16;i>=0;--i)
45         if(Tfa[v][i]!=Tfa[u][i]){v=Tfa[v][i];u=Tfa[u][i];}
46     return Tfa[v][0];
47 }
48 int GetAns(int v,int u){
49     int lca=GetLca(v,u);
50     int Min=Inf,Max=0,ans=0;
51     for(int i=16;i>=0;--i)
52         if((Tdep[v]-Tdep[lca])&(1<<i)){
53             ans=max(ans,max(Tup[v][i],Tmax[v][i]-Min));
54             Min=min(Min,Tmin[v][i]);
55             v=Tfa[v][i];
56         }
57     for(int i=16;i>=0;--i)
58         if((Tdep[u]-Tdep[lca])&(1<<i)){
59             ans=max(ans,max(Tdown[u][i],Max-Tmin[u][i]));
60             Max=max(Max,Tmax[u][i]);
61             u=Tfa[u][i];
62         }
63     return max(ans,Max-Min);
64 }
65 int main(){
66     //freopen("in.txt","r",stdin);
67     //freopen("out.txt","w",stdout);
68     int n,q;
69     n=Read();
70     for(int i=1;i<=n;++i)
71         Tval[i]=Read();
72     for(int i=1,a,b;i<n;++i){
73         a=Read();b=Read();
74         addedge(a,b);
75     }
76     LcaInit(1);
77     q=Read();
78     for(int i=1,a,b,ans;i<=q;++i){
79         a=Read();b=Read();
80         ans=GetAns(a,b);
81         printf("%d
",ans);
82     }
83     //fclose(stdin);fclose(stdout);
84     return 0;
85 }

算法三:

 1 #include <cstdio>
 2 #include <algorithm>
 3 const int Inf=1e9;
 4 int Rt[50005];
 5 bool vis[50005];
 6 int Tmin[50005],Tmax[50005],Tup[50005],Tdown[50005];
 7 int Gsize,Qsize,Asize,Gfirst[50005],Qfirst[50005],Afirst[50005];
 8 struct GEdge{int to,next;}Ge[100005];
 9 struct QEdge{int to,id,next;}Qe[100005];
10 struct AEdge{int id,next;}Ae[100005];
11 struct Query{int u,v,ans;}Que[100005];
12 int Read(){
13     int ch='@',t=0;
14     for(;ch<48 || 57<ch;ch=getchar());
15     for(;47<ch && ch<58;ch=getchar())t=t*10+ch-48;
16     return t;
17 } 
18 inline int max(int x,int y) {x-=y;return y+(x&(~(x>>31)));}
19 inline int min(int x,int y) {x-=y;return y+(x&(x>>31));}
20 void Gaddedge(int x,int y){
21     Ge[++Gsize].to=y;Ge[Gsize].next=Gfirst[x];Gfirst[x]=Gsize;
22     Ge[++Gsize].to=x;Ge[Gsize].next=Gfirst[y];Gfirst[y]=Gsize;
23 }
24 void Qaddedge(int x,int y,int id){
25     Qe[++Qsize].to=y;Qe[Qsize].id=id;Qe[Qsize].next=Qfirst[x];Qfirst[x]=Qsize;
26     Qe[++Qsize].to=x;Qe[Qsize].id=id;Qe[Qsize].next=Qfirst[y];Qfirst[y]=Qsize;
27 }
28 void Aaddedge(int x,int id){
29     Ae[++Asize].id=id;Ae[Asize].next=Afirst[x];Afirst[x]=Asize;
30 }
31 int GetRt(int v){
32     if(Rt[v]==v)return v;
33     int fa=Rt[v];
34     Rt[v]=GetRt(Rt[v]);
35     Tup[v]=max(max(Tup[v],Tup[fa]),Tmax[fa]-Tmin[v]);
36     Tdown[v]=max(max(Tdown[v],Tdown[fa]),Tmax[v]-Tmin[fa]);
37     Tmin[v]=min(Tmin[v],Tmin[fa]);
38     Tmax[v]=max(Tmax[v],Tmax[fa]);
39     return Rt[v];
40 }
41 void Tarjan(int v){
42     vis[v]=true;
43     for(int i=Qfirst[v],u,lca;i;i=Qe[i].next){
44         u=Qe[i].to;if(!vis[u])continue;
45         lca=GetRt(u); 
46         Aaddedge(lca,Qe[i].id);
47     }
48     for(int i=Gfirst[v],u;i;i=Ge[i].next){
49         u=Ge[i].to;if(vis[u])continue;
50         Tarjan(u);
51         Rt[u]=v;
52     }
53     for(int i=Afirst[v],id,tv,tu;i;i=Ae[i].next){
54         id=Ae[i].id;tv=Que[id].v;tu=Que[id].u;
55         GetRt(tv);GetRt(tu);
56         Que[id].ans=max(max(Tup[tv],Tdown[tu]),Tmax[tu]-Tmin[tv]);
57     }
58 }
59 int main(){
60     //freopen("in.txt","r",stdin);
61     //freopen("out.txt","w",stdout);
62     int n,q;
63     n=Read();
64     for(int i=1;i<=n;++i)
65         Rt[i]=i;
66     for(int i=1;i<=n;++i)
67         Tmin[i]=Tmax[i]=Read();
68     for(int i=1,a,b;i<n;++i){
69         a=Read();b=Read();
70         Gaddedge(a,b);
71     }
72     q=Read();
73     for(int i=1;i<=q;++i){
74         Que[i].v=Read();Que[i].u=Read();
75         Qaddedge(Que[i].v,Que[i].u,i);
76     }
77     Tarjan(1);
78     for(int i=1;i<=q;++i)
79         printf("%d
",Que[i].ans);
80     //fclose(stdin);fclose(stdout);
81     return 0;
82 }
原文地址:https://www.cnblogs.com/hjj1871984569/p/6005578.html