[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. 201621123040《Java程序设计》第十四周学习总结

    1.本周学习总结 1.1以你喜欢的方式(思维导图或其他)归纳总结与数据库相关内容. 显示所有数据库: show databases; 创建数据库: create database test; 删除数据 ...

  2. I/O多路转接之poll 函数

    poll 一.poll()函数: 这个函数是某些Unix系统提供的用于执行与select()函数同等功能的函数,自认为poll和select大同小异,下面是这个函数的声明: #include < ...

  3. JAVA的循环控制与循环嵌套

    循环控制和循环嵌套 循环控制是除了循环条件之外,控制循环是否进行的一个机制,这给处理循环问题带来了灵活性.循环体内的语句块可以是顺序执行的语句,可以是分支结构的语句,也可以是循环语句,循环中含循环,就 ...

  4. DML数据操作语言之谓词,case表达式

    谓词:就是返回值是真值的函数. 前面接触到的“>” “<” “=”等称为比较运算符,它们的正式名称就是比较谓词.因为它们比较之后返回的结果是真值. 由于谓词 返回的结果是一个真值 ,即tr ...

  5. 常用Mysql数据库操作语句

    用户管理: 1.新建用户: 语法msyql>CREATE USER 'username'@'host' IDENTIFIED BY 'password'; 说明: username - 你将创建 ...

  6. [JCIP笔记] (三)如何设计一个线程安全的对象

    在当我们谈论线程安全时,我们在谈论什么中,我们讨论了怎样通过Java的synchronize机制去避免几个线程同时访问一个变量时发生问题.忧国忧民的Brian Goetz大神在多年的开发过程中,也悟到 ...

  7. 爬虫模块BeautifulSoup

    中文文档:https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html# 1.1      安装BeautifulSoup模块 ...

  8. Python内置函数(18)——bin

    英文文档: bin(x) Convert an integer number to a binary string. The result is a valid Python expression. ...

  9. Docker学习笔记 - Docker部署nginx网站

    一.制作 nginx 镜像 1.下载配置文件 mkdir /opt/nginx_docker && cd /opt/nginx_docker mkdir nginx && ...

  10. hadoop2.6.0理论:hdfs、yarn、mapreduce的架构

    HDFS2的架构:负责数据的分布式存储 主从结构 主节点,可以有2个: namenode 从节点,有很多个: datanode namenode负责: 接收用户操作请求,是用户操作的入口 维护文件系统 ...