题意:有一种商品。在N个城市中的价格都不一样、给定N个点和N-1条边。有Q个询问。每个询问的内容为:
商人从u-->v这条路径上所能获得的最大利润是多少、商人只可以在某一个点买进东西。在这个点之后卖出它、
思路:
由于给定的是一颗简单树。很容易就想到可以用LCA来做。难点在于。怎么求出u-->t-->v的最大利润,
t==lca(u,v)
可以想到并查集的更新操作。
对于每一个询问的u和v 如果我知道以下内容:
1) u到最近的祖先的最大利润up[u] 和 最近祖先到u的最大利润 down[u]
2) u到最近祖先的最大值maxx[u] 和最小值 minx[u]
那么我们就可以很容易求出u-->v的最大利润了
u-->v的最大利润 = max(up[u],down[v],maxx[v]-minx[u])
但是主要的问题怎么解决
通过tarjan递归的时候结局 和 并查集中的Find来处理。
详情代码:
//author: CHC //First Edit Time: 2014-08-02 21:59 //Last Edit Time: 2014-08-02 22:40 #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <set> #include <vector> #include <map> #include <queue> #include <set> #include <algorithm> using namespace std; #define MAXN 50010 struct Q { int u,v,id,dir; Q(){} Q(int _u,int _v,int _id,int _dir):u(_u),v(_v),id(_id),dir(_dir){} }; int path[MAXN]; vector <int> e[MAXN]; vector <Q> h[MAXN],q[MAXN]; int maxx[MAXN],minx[MAXN],up[MAXN],down[MAXN],n,ans[MAXN]; int vis[MAXN]; inline void init(){ for(int i=0;i<=n+3;i++){ path[i]=i; vis[i]=up[i]=down[i]=0; e[i].clear(); h[i].clear(); q[i].clear(); } } int Find(int x){ if(x==path[x])return x; int px=path[x]; path[x]=Find(path[x]); up[x]=max(maxx[px]-minx[x],max(up[x],up[px])); down[x]=max(maxx[x]-minx[px],max(down[x],down[px])); maxx[x]=max(maxx[x],maxx[px]); minx[x]=min(minx[x],minx[px]); return path[x]; } void LCA(int u){ vis[u]=1; for(int i=0;i<(int)q[u].size();i++){ Q &next=q[u][i]; if(vis[next.v]){ int lca=Find(next.v); h[lca].push_back(next); } } for(int i=0;i<(int)e[u].size();i++){ int v=e[u][i]; if(!vis[v]){ LCA(v); path[v]=u; } } for(int i=0;i<(int)h[u].size();i++){ Q now=h[u][i]; Find(now.u); Find(now.v); if(!now.dir) swap(now.u,now.v); ans[now.id]=max(up[now.u],down[now.v]); ans[now.id]=max(ans[now.id],maxx[now.v]-minx[now.u]); } } int main() { while(~scanf("%d",&n)){ init(); for(int i=1,x;i<=n;i++){ scanf("%d",&x); maxx[i]=minx[i]=x; } for(int i=1,x,y;i<n;i++){ scanf("%d%d",&x,&y); e[x].push_back(y); e[y].push_back(x); } int qq; scanf("%d",&qq); for(int i=0,x,y;i<qq;i++){ scanf("%d%d",&x,&y); q[x].push_back(Q(x,y,i,1)); q[y].push_back(Q(y,x,i,0)); } LCA(1); for(int i=0;i<qq;i++) printf("%d\n",ans[i]); } return 0; }