[POJ 3728]The merchant
Description
There are N cities in a country, and there is one and only one simple path between each pair of cities. A merchant has chosen some paths and wants to earn as much money as possible in each path. When he move along a path, he can choose one city to buy some goods and sell them in a city after it. The goods in all cities are the same but the prices are different. Now your task is to calculate the maximum possible profit on each path.
Input
The first line contains N, the number of cities.
Each of the next N lines contains wi the goods' price in each city.
Each of the next N-1 lines contains labels of two cities, describing a road between the two cities.
The next line contains Q, the number of paths.
Each of the next Q lines contains labels of two cities, describing a path. The cities are numbered from 1 to N.
1 ≤ N, wi, Q ≤ 50000
Output
The output contains Q lines, each contains the maximum profit of the corresponding path. If no positive profit can be earned, output 0 instead.
Sample Input
4
1
5
3
2
1 3
3 2
3 4
9
1 2
1 3
1 4
2 3
2 1
2 4
3 1
3 2
3 4
Sample Output
4
2
2
0
0
0
0
2
0
题解
题解:因为没有修改,所以我们可以使用树上倍增来解决,
设 $fa[i][j]$表示点 $i$ 的第 $2^j$ 个祖先
$ma[i][j]$表示点 $i$ 到点 $fa[i][j]$的最大值。
$mi[i][j]$表示点 $i$ 到点 $fa[i][j]$的最小值。
$zma[i][j]$表示点 $i$ 到点 $fa[i][j]$的最大获利。
$fma[i][j]$表示点 $fa[i][j]$到点 $i$ 的最大获利。
然后我们可以预处理出这四个数组。
即:
ma[x][i]=max(ma[fa[x][i-]][i-],ma[x][i-]);
mi[x][i]=min(mi[fa[x][i-]][i-],mi[x][i-]);
zma[x][i]=max(max(zma[fa[x][i-]][i-],zma[x][i-]),ma[fa[x][i-]][i-]-mi[x][i-]);
fma[x][i]=max(max(fma[fa[x][i-]][i-],fma[x][i-]),ma[x][i-]-mi[fa[x][i-]][i-]);
在走向最近公共祖先的路径上记录一下历史最小值,在远离最近公共祖先的路径上记录一下历史最大值(在途中和最大获利比较)。最后答案再和历史最大值-历史最小值比较一下即可。
//It is made by Awson on 2017.10.13
#include <set>
#include <map>
#include <cmath>
#include <ctime>
#include <stack>
#include <queue>
#include <string>
#include <cstdio>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define LL long long
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Max(a, b) ((a) > (b) ? (a) : (b))
using namespace std;
const int N = ;
const int INF = 1e9; int n, m, u, v, lim;
struct tt {
int to, next;
}edge[(N<<)+];
int path[N+], top;
int cost[N+];
int dep[N+], fa[N+][], maxn[N+][], minn[N+][], up[N+][], down[N+][]; void add(int u, int v) {
edge[++top].to = v;
edge[top].next = path[u];
path[u] = top;
}
void dfs(int u, int depth) {
dep[u] = depth;
for (int i = path[u]; i; i = edge[i].next)
if (dep[edge[i].to] == ) {
maxn[edge[i].to][] = Max(cost[edge[i].to], cost[u]);
minn[edge[i].to][] = Min(cost[edge[i].to], cost[u]);
up[edge[i].to][] = Max(, cost[u]-cost[edge[i].to]);
down[edge[i].to][] = Max(, cost[edge[i].to]-cost[u]);
fa[edge[i].to][] = u;
dfs(edge[i].to, depth+);
}
}
void ST() {
for (int t = ; t <= lim; t++)
for (int i = ; i <= n; i++) {
int v = fa[i][t-];
fa[i][t] = fa[v][t-];
maxn[i][t] = Max(maxn[i][t-], maxn[v][t-]);
minn[i][t] = Min(minn[i][t-], minn[v][t-]);
up[i][t] = Max(up[i][t-], up[v][t-]), up[i][t] = Max(up[i][t], maxn[v][t-]-minn[i][t-]);
down[i][t] = Max(down[i][t-], down[v][t-]), down[i][t] = Max(down[i][t], maxn[i][t-]-minn[v][t-]);
}
}
int get_lca(int u, int v) {
if (dep[u] < dep[v]) swap(u, v);
for (int i = lim; i >= ; i--)
if (dep[fa[u][i]] >= dep[v])
u = fa[u][i];
if (u != v) {
for (int i = lim; i >= ; i--)
if (fa[u][i] != fa[v][i])
u = fa[u][i], v = fa[v][i];
u = fa[u][], v = fa[v][];
}
return u;
}
int get_ans(int u, int v) {
int lca = get_lca(u, v);
int ans = , large = -INF, small = INF;
for (int i = lim; i >= ; i--)
if (dep[fa[u][i]] >= dep[lca]) {
ans = Max(ans, up[u][i]);
ans = Max(ans, maxn[u][i]-small);
small = Min(small, minn[u][i]);
u = fa[u][i];
}
for (int i = lim; i >= ; i--)
if (dep[fa[v][i]] >= dep[lca]) {
ans = Max(ans, down[v][i]);
ans = Max(ans, large-minn[v][i]);
large = Max(large, maxn[v][i]);
v = fa[v][i];
}
return Max(ans, large-small);
} void work() {
scanf("%d", &n); lim = log(n*.)/log(*.);
for (int i = ; i <= n; i++) scanf("%d", &cost[i]);
for (int i = ; i < n; i++) {
scanf("%d%d", &u, &v);
add(u, v), add(v, u);
}
dfs(, ); ST();
scanf("%d", &m);
while (m--) {
scanf("%d%d", &u, &v);
printf("%d\n", get_ans(u, v));
}
}
int main() {
work();
return ;
}
[POJ 3728]The merchant的更多相关文章
- [最近公共祖先] POJ 3728 The merchant
The merchant Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 4556 Accepted: 1576 Desc ...
- poj 3728 The merchant(LCA)
Description There are N cities in a country, and there is one and only one simple path between each ...
- POJ 3728 The merchant(并查集+DFS)
[题目链接] http://poj.org/problem?id=3728 [题目大意] 给出一棵树,每个点上都可以交易货物,现在给出某货物在不同点的价格, 问从u到v的路程中,只允许做一次买入和一次 ...
- poj——3728 The merchant
The merchant Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 5055 Accepted: 1740 Desc ...
- POJ 3728 The merchant(LCA+DP)
The merchant Time Limit : 6000/3000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other) Total ...
- poj 3728 The merchant 倍增lca求dp
题目: zdf给出的题目翻译: 从前有一个富饶的国度,在这里人们可以进行自由的交易.这个国度形成一个n个点的无向图,每个点表示一个城市,并且有一个权值w[i],表示这个城市出售或收购这个权值的物品.又 ...
- POJ 3728 The merchant (树形DP+LCA)
题目:https://vjudge.net/contest/323605#problem/E 题意:一棵n个点的树,然后有m个查询,每次查询找(u->v)路径上的两个数,a[i],a[j],(i ...
- POJ——T 3728 The merchant
http://poj.org/problem?id=3728 Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 5068 A ...
- POJ - 3728:The merchant (Tarjan 带权并查集)
题意:给定一个N个节点的树,1<=N<=50000 每个节点都有一个权值,代表商品在这个节点的价格.商人从某个节点a移动到节点b,且只能购买并出售一次商品,问最多可以产生多大的利润. 思路 ...
随机推荐
- java编程思想笔记(1)
java编程思想笔记(1) 一,对象的创建和生命周期 对象的数据位于何处?怎样控制对象的生命周期? 在堆(heap)的内存池中动态地创建对象. java完全采用了动态内存分配方式. 二,垃圾回收器 自 ...
- [福大软工] W班 软件产品案例分析
作业要求 https://edu.cnblogs.com/campus/fzu/FZUSoftwareEngineering1715W/homework/1300 评分细则 第一部分 调研,评测 (3 ...
- C语言--第14.15周作业
一. 7-3 将数组中的数逆序存放 1.代码 #include 2<stdio.h> int main() { int a[10]; int i, n, s; scanf("%d ...
- 使用XIB的UITableViewCell自适应,以及出现的问题进行解决
1.首先需要定义一个属性 @property (nonatomic, strong) UITableViewCell *prototypeCell; 2.在创建完tableView后加上如下代码 se ...
- linux作为服务器,利用top命令查看服务进程的耗用情况
top命令查看进程服务如下: 其中shift+m可以按照内存的消耗进行排序,shift+p是按照cpu的消耗进程,排序,其中对cpu的消耗是一定时间,谁占用的时间越长消耗越大, 还有按空格键,会刷新一 ...
- Linux入门(2)_给初学者的建议
1 学习Linux的注意事项 严格区分大小写(命令, 文件, 选项) Linux中所有内容以文件形式保存, 包括硬件 硬盘文件是/dev/sd[a-p] 光盘文件是/dev/sr0等 Linux不靠扩 ...
- Spring Security 入门(1-3-2)Spring Security - http元素 - intercept-url配置
http元素下可以配置登录页面,也可以配置 url 拦截. 1.直接配置拦截url和对应的访问权限 <security:http use-expressions="false" ...
- SpringCloud是什么?
参考链接: http://blog.csdn.net/forezp/article/details/70148833 一.概念定义 Spring Cloud是一个微服务框架,相比Dubbo ...
- Python之线程
操作系统线程理论 线程概念的引入背景 进程 之前我们已经了解了操作系统中进程的概念,程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程.程序和进程的区别 ...
- Mysql中autocommit的用法
定义 Mysql文档原文:SET autocommit disables or enables the default autocommit mode for the current session. ...