[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]);

在走向最近公共祖先的路径上记录一下历史最小值,在远离最近公共祖先的路径上记录一下历史最大值(在途中和最大获利比较)。最后答案再和历史最大值-历史最小值比较一下即可

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Node
{
int next,to;
}edge[];
int head[],num,ans,dep[],val[],flag,n,Q;
int fa[][],Min[][],Max[][],Up[][],Down[][];
void add(int u,int v)
{
num++;
edge[num].next=head[u];
head[u]=num;
edge[num].to=v;
}
void dfs(int x,int pa)
{int i;
if (dep[x]) return;
dep[x]=dep[pa]+;
for (i=;i<=;i++)
{
fa[x][i]=fa[fa[x][i-]][i-];
Max[x][i]=max(Max[x][i-],Max[fa[x][i-]][i-]);
Min[x][i]=min(Min[x][i-],Min[fa[x][i-]][i-]);
Up[x][i]=max(Up[x][i-],Up[fa[x][i-]][i-]);
Up[x][i]=max(Up[x][i],Max[fa[x][i-]][i-]-Min[x][i-]);
Down[x][i]=max(Down[x][i-],Down[fa[x][i-]][i-]);
Down[x][i]=max(Down[x][i],Max[x][i-]-Min[fa[x][i-]][i-]);
}
for (i=head[x];i;i=edge[i].next)
{
int v=edge[i].to;
if (v!=pa)
{
Max[v][]=max(val[v],val[x]);
Min[v][]=min(val[v],val[x]);
Up[v][]=max(,val[x]-val[v]);
Down[v][]=max(,val[v]-val[x]);
fa[v][]=x;
dfs(v,x);
}
}
}
int LCA(int x,int y)
{
int i;
if (dep[x]<dep[y]) swap(x,y);
for (i=;i>=;i--)
if ((<<i)<=dep[x]-dep[y])
{
x=fa[x][i];
}
if (x==y)
{
//cout<<"LCA:"<<' '<<x<<endl;
return x;
}
for (i=;i>=;i--)
if (fa[x][i]!=fa[y][i])
{
x=fa[x][i];
y=fa[y][i];
}
x=fa[x][];
y=fa[y][];
//cout<<"LCA:"<<' '<<x<<endl;
return x;
}
void get_ans(int x,int y,int lca)
{int i;
int a=,b=,minv=2e9,maxv=;
int small=2e9,large=;
for (i=;i>=;i--)
if ((<<i)<=dep[x]-dep[lca])
{
b=max(b,Up[x][i]);
b=max(b,Max[x][i]-small);
small=min(small,Min[x][i]);
minv=min(minv,Min[x][i]);
x=fa[x][i];
}
for (i=;i>=;i--)
if ((<<i)<=dep[y]-dep[lca])
{
a=max(a,Down[y][i]);
a=max(a,large-Min[y][i]);
large=max(large,Max[y][i]);
maxv=max(maxv,Max[y][i]);
y=fa[y][i];
}
ans=max(a,max(b,maxv-minv));
return;
}
int main()
{int i,u,v,x,y;
freopen("business.in","r",stdin);
freopen("business.out","w",stdout);
cin>>n;
memset(Min,,sizeof(Min));
for (i=;i<=n;i++)
scanf("%d",&val[i]);
for (i=;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
dfs(,);
cin>>Q;
while (Q--)
{
scanf("%d%d",&x,&y);
if (x==y) printf("0\n");
else
{
int lca=LCA(x,y);
get_ans(x,y,lca);
printf("%d\n",ans);
}
}
}

poj3728 商务旅行的更多相关文章

  1. 倍增法-lca codevs 1036 商务旅行

    codevs 1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 某首都城市的商人要经常到各城镇去做生意 ...

  2. C++之路进阶——codevs1036(商务旅行)

    1036 商务旅行 题目描述 Description 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇 ...

  3. 【codevs1036】商务旅行 LCA 倍增

    1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题目描述 Description 某首都城市的商人要经常到各城镇去做生意,他们按自己的 ...

  4. 2953: [Poi2002]商务旅行

    2953: [Poi2002]商务旅行 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 8  Solved: 8[Submit][Status] Desc ...

  5. CodeVs.1036 商务旅行 ( LCA 最近公共祖先 )

    CodeVs.1036 商务旅行 ( LCA 最近公共祖先 ) 题意分析 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从 ...

  6. codevs——1036 商务旅行

    1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 Description 某首都城市的商人要经常 ...

  7. codevs1036商务旅行(LCA)

    1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 某首都城市的商人要经常到各城镇去做 ...

  8. codevs1026商务旅行

    1036 商务旅行  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解       题目描述 Description 某首都城市的商人要经常到各城镇去做 ...

  9. codevs 1036 商务旅行(Targin求LCA)

    传送门 Description 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意 ...

随机推荐

  1. Bate版敏捷冲刺报告--day0

    1 团队介绍 团队组成: PM:齐爽爽(258) 小组成员:马帅(248),何健(267),蔡凯峰(285)  Git链接:https://github.com/WHUSE2017/C-team 2 ...

  2. 在深度linux下安装pip3与jupyter

    前言 以下安装说明基于已经正确安装python3 文件下载 https://pypi.python.org/pypi/pip 下载pip-9.0.1.tar.gz (md5, pgp)文件 安装准备工 ...

  3. Python习题(第一课)

    想了想其他的太简单了,还是不放了,剩三题吧. 一.完美立方 编写一个程序,对任给的正整数N (N≤100),寻找所有的四元组(a, b, c, d),使得a^3= b^3 + c^3 + d^3,其中 ...

  4. linux系统增加开机启动服务/应用

    操作 在/etc/init.d下新建示例脚本文件(customize.sh),该脚本会启动zookeeper服务.内容如下: #!/bin/sh /usr/local/zookeeper-/bin/z ...

  5. 数据结构与算法 —— 链表linked list(01)

    链表(维基百科) 链表(Linked list)是一种常见的基础数据结构,是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer).由于不必须按顺序存储, ...

  6. NFS PersistentVolume - 每天5分钟玩转 Docker 容器技术(151)

    上一节我们介绍了 PV 和 PVC,本节通过 NFS 实践. 作为准备工作,我们已经在 k8s-master 节点上搭建了一个 NFS 服务器,目录为 /nfsdata: 下面创建一个 PV mypv ...

  7. Centos6.7的在虚拟机virulBox下的lamp平台的搭建

    实验环境: linux:小甲鱼带你学C语言,带你飞的提供的体积比较小的centos6.7和virtualBox mysql,apahce,php是燕十八在Linux基础进阶中提供的安装方式: 结果,安 ...

  8. 《网络》:设置三个密码:通过console口连接设备,进入特权模式,登录Telnet

    软件:Cisco Packet Tracer Instructor 软件下载链接在上一篇文章中. 内容:通过设置三个密码,熟悉采用Telnet方式配置交换机的方法. 细节说明:计算机的IP地址和交换机 ...

  9. 说说cglib动态代理

    前言 jdk中的动态代理通过反射类Proxy和InvocationHandler回调接口实现,要求委托类必须实现一个接口,只能对该类接口中定义的方法实现代理,这在实际编程中有一定的局限性. cglib ...

  10. 1.phpStrom连接远程代码

    1.选择一个新的文件 2.选择自己需要的传输方式 3.添加项目名+路径 4.填写连接基本信息 5.配置成功,下载完毕后,设计本地与远程代码同步修改 自此本地修改代码,同时修改远程服务器代码就设置完毕~ ...