思路理解,但是代码实现不行,其中是并查集更新他复杂了,,,另外,可以用RMQ来搞。代码是修改别人的代码的。
转:
题意:给出一棵节点有值的树,给出Q个询问(a,b),问从a到b的最大盈利(即:先在最小值买入,再在最大值卖出)
分析:这题其实就是在一棵树上找RMQ,于是很多人都转化为rmq问题来做,尽管都说非常好做,但是由于本菜对RMQ实在不熟悉,花了整整一个下午半个晚上来想rmq的转移。。。无果,后来看到一篇博客印证了一开始我的想法是对的,只要在求LCA时,并查集合并的时候更新一些数据即可
假设 询问Q(x,y)LCA(x,y)=z
即记录 max(x) x到z路径上的最大值
min(x) x到z路径上的最小值
up(x) x到z的最优解
down(x) z到x的最优解
于是答案=MAX(max(y)-min(x),up(x),down(y));
对应的:
最小价格 (从祖先走到自己的最大价格)max
最大价格 (从祖先走到自己的最小价格)min
最大收益(从自己走到祖先)metomax
最大收益(从祖先走到自己)tomemax
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdio>
using namespace std;
#define nNode 50005
int Max (int a,int b)
{
return a>b?a:b;
}
int Min (int a,int b)
{
return a<b?a:b;
}
struct Node
{
int father,minn,maxx,tomemax,metomax;
}Set[nNode];
struct Query
{
int v,id,opp;//opp 表示 s->v or v->s
Query(int a,int b,int c)
{v=a;id=b;opp=c;};
};
vector <int> tree[nNode];
vector <Query> Q[nNode];
bool color[nNode];
int value[nNode];
int ans[nNode];
int pre[nNode];
void Init(int n)
{
int i;
for(i=0;i<=n;i++)
{
tree[i].clear();
Q[i].clear();
color[i]=false;
Set[i].father=i;
Set[i].maxx=value[i];//一开始每个点在一个集合里 所以max,min =自己价格;
Set[i].metomax=0;
Set[i].minn=value[i];
Set[i].tomemax=0;
}
}
int Find(int x)
{
int px=Set[x].father;//其父节点
if(x!=px)
{
Set[x].father=Find(px);
Set[x].metomax=Max(Set[px].metomax,Max(Set[x].metomax,Set[px].maxx-Set[x].minn));//更新metomax
Set[x].tomemax=Max(Set[px].tomemax,Max(Set[x].tomemax,Set[x].maxx-Set[px].minn));
Set[x].maxx=Max(Set[x].maxx,Set[px].maxx);
Set[x].minn=Min(Set[x].minn,Set[px].minn);
}
return Set[x].father;
}
void Union(int x, int y)
{
Set[Find(x)].father = Set[Find(y)].father;
}
void LCA(int s)
{
int i,sz,t;
sz=tree[s].size();
for(i=0;i<sz;i++)
{
t=tree[s][i];
if(t!=pre[s])
{
pre[t]=s;
LCA(t);
Union(tree[s][i],s);
}
}
color[s]=true;
sz=Q[s].size();
for(i=0;i<sz;i++)
{
if(color[Q[s][i].v])//注意这里只又算到了 从公共祖先到Q[s].v的信息,而s到公共祖先的信息却没有
{
t=Find(Q[s][i].v);
int v,mi,ma,tomax;//下面是求s到公共祖先的信息
mi=ma=value[s];
tomax=0;
v=s;
if(Q[s][i].opp==0) //s->Q[s][i].v
{
while(v!=t)
{
tomax=Max(Set[v].metomax,Max(tomax,Set[v].maxx-mi));
mi=Min(mi,Set[v].minn);
v=pre[v];
}
ans[Q[s][i].id]=Max(Max(tomax,Set[Q[s][i].v].tomemax),Set[Q[s][i].v].maxx-mi);
}
else
{
while(v!=t)
{
tomax=Max(Set[v].tomemax,Max(tomax,ma-Set[v].minn));
ma=Max(ma,Set[v].maxx);
v=pre[v];
}
ans[Q[s][i].id]=Max(Max(tomax,Set[Q[s][i].v].metomax),ma-Set[Q[s][i].v].minn);
}
}
}
}
int main()
{
int n,i,a,b;
while(scanf("%d",&n)!=EOF)
{
for(i=1;i<=n;i++)
scanf("%d",&value[i]);
Init(n);
for(i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
tree[a].push_back(b);
tree[b].push_back(a);
}
scanf("%d",&n);
for(i=0;i<n;i++)
{
scanf("%d%d",&a,&b);
Q[a].push_back(Query(b,i,0));
Q[b].push_back(Query(a,i,1));
}
LCA(1);
for(i=0;i<n;i++)
{
printf("%d\n",ans[i]);
}
}
return 0;
}