poj3728The merchant 【倍增】【LCA】
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
倍增 LCA还是完全不会写.....
所以是看的题解
刚开始完全不能理解为什么这道题也能转换成LCA 找得到公共祖先然后呢 然后呢 然后呢
建的图相当于一个dfs树 路径是唯一的
找公共祖先t就相当于找到这条路径 公共祖先把这个路径分成了两半
最后(u, v)的答案有三种可能
1.u到t完成了买和卖
2.t到v完成了买和卖
3.在u到t某点买,t到v某点卖
因此现在需要一个up数组,up[i][j]维护i到i节点往上2^j的节点的最大差价
down数组,down[i][j]维护i到i节点往下2^j的节点的最大差价
Max数组, Max[i][j]维护i到i节点往上2^j的节点之间价格的最大值
Min数组,Min[i][j]维护i到i节点往上2^j的节点之间价格的最小值
parent数组,parent[i][0]存储每个节点的父亲,用dfs先预处理出来。用倍增的思想处理出parent[i][j]表示i往上2^j的节点
#include <iostream>
#include <algorithm>
#include <stdlib.h>
#include <cstring>
#include <vector>
#include <map>
#include <set>
#include <stdio.h>
#include <queue>
#include <stack>
#define inf 0x3f3f3f3f
using namespace std;
int n, q, ecnt;
const int maxn = 50005;
int Max[maxn][20], Min[maxn][20], up[maxn][20], down[maxn][20], parent[maxn][20];
vector <int> g[maxn];
int dep[maxn],val[maxn];
void dfs(int u, int fa)
{
for(int i = 0; i < g[u].size(); i++){
int v = g[u][i];
if(v == fa) continue;
dep[v] = dep[u] + 1;
parent[v][0] = u;
Max[v][0] = max(val[v], val[u]);
Min[v][0] = min(val[v], val[u]);
down[v][0] = max(0, val[v] - val[u]);
up[v][0] = max(0, val[u] - val[v]);
dfs(v, u);
}
}
void init()
{
dep[1] = 1;
memset(parent, -1, sizeof(parent));
dfs(1, 0);
for(int j = 1; (1 << j) <= n; j++){
for(int i = 1; i <= n; i++){
if(~parent[i][j - 1]){
int k = parent[i][j - 1], a, b;
parent[i][j] = parent[k][j - 1];
Max[i][j] = max(Max[i][j - 1], Max[k][j - 1]);
Min[i][j] = min(Min[i][j - 1], Min[k][j - 1]);
a = max(0, Max[i][j - 1] - Min[k][j - 1]), b = max(down[i][j - 1], down[k][j - 1]);
down[i][j] = max(a, b);
a = max(0, Max[k][j - 1] - Min[i][j - 1]), b = max(up[i][j - 1], up[k][j - 1]);
up[i][j] = max(a,b);
}
}
}
}
int LCA(int a, int b)
{
if(dep[a] < dep[b]) swap(a, b);
int i;
for(i = 0; (1 << i) <= dep[a]; i++);
i--;
for(int j = i; j >= 0; j--){
if(dep[a] - (1 << j) >= dep[b]){
a = parent[a][j];
}
}
if(a == b){
return a;
}
for(int j = i; j >= 0; j--){
if(parent[a][j] != -1 && parent[a][j] != parent[b][j]){
a = parent[a][j];
b = parent[b][j];
}
}
return parent[a][0];
}
int query_down(int x, int k, int &max_val)
{
int ans = 0;
max_val = 0;
for(int i = 18; i >= 0; i--){
if(k & (1 << i)){
ans = max(ans, down[x][i]);
ans = max(ans, max_val - Min[x][i]);
max_val = max(max_val, Max[x][i]);
x = parent[x][i];
}
}
return ans;
}
int query_up(int x, int k, int &min_val)
{
int ans = 0;
min_val = inf;
for(int i = 18; i >= 0; i--){
if(k & (1 << i)){
ans = max(ans, up[x][i]);
ans = max(ans, Max[x][i] - min_val);
min_val = min(min_val, Min[x][i]);
x = parent[x][i];
}
}
return ans;
}
int main()
{
while(scanf("%d", &n) != EOF){
for(int i = 1; i <= n; i++){
scanf("%d", &val[i]);
}
for(int i = 1; i <= n; i++){
g[i].clear();
}
for(int i = 1; i < n; i++){
int u, v;
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
init();
scanf("%d", &q);
while(q--){
int u, v;
scanf("%d%d", &u, &v);
int t = LCA(u, v);
int min_val, max_val, a, b;
a = query_up(u, dep[u] - dep[t], min_val);
b = query_down(v, dep[v] - dep[t], max_val);
int ans = max(max(0, max_val - min_val), max(a, b));
cout<<ans<<endl;
}
}
return 0;
}
poj3728The merchant 【倍增】【LCA】的更多相关文章
- POJ3728The merchant (倍增)(LCA)(DP)(经典)(||并查集压缩路径?)
There are N cities in a country, and there is one and only one simple path between each pair of citi ...
- poj 3728 The merchant 倍增lca求dp
题目: zdf给出的题目翻译: 从前有一个富饶的国度,在这里人们可以进行自由的交易.这个国度形成一个n个点的无向图,每个点表示一个城市,并且有一个权值w[i],表示这个城市出售或收购这个权值的物品.又 ...
- [板子]倍增LCA
倍增LCA板子,没有压行,可读性应该还可以.转载请随意. #include <cstdio> #include <cstring> #include <algorithm ...
- 洛谷P3128 [USACO15DEC]最大流Max Flow [倍增LCA]
题目描述 Farmer John has installed a new system of pipes to transport milk between the stalls in his b ...
- Gym100685G Gadget Hackwrench(倍增LCA)
题目大概说一棵边有方向的树,q个询问,每次询问结点u是否能走到v. 倍增LCA搞即可: 除了par[k][u]表示u结点往上走2k步到达的结点, 再加上upp[k][u]表示u结点往上走2k步经过边的 ...
- Codeforces 418d Big Problems for Organizers [树形dp][倍增lca]
题意: 给你一棵有n个节点的树,树的边权都是1. 有m次询问,每次询问输出树上所有节点离其较近结点距离的最大值. 思路: 1.首先是按照常规树形dp的思路维护一个子树节点中距离该点的最大值son_di ...
- hdu 4674 Trip Advisor(缩点+倍增lca)
花了一天半的时间,才把这道题ac= = 确实是道好题,好久没敲这么长的code了,尤其是最后的判定,各种销魂啊~ 题目中给出的条件最值得关注的就是:每个点最多只能在一个环内->原图是由一个个边连 ...
- Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序
题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s 内存限制:512.0MB 总提交次数:196 AC次数:65 平均分: ...
- codevs 1036 商务旅行 (倍增LCA)
/* 在我还不知道LCA之前 暴力跑的SPFA 70分 三个点TLE */ #include<iostream> #include<cstdio> #include<cs ...
随机推荐
- InnoDB锁问题 & DB事务隔离级别
<参考:http://www.cnblogs.com/jack204/archive/2012/06/09/2542940.html>InnoDB行锁实现方式InnoDB行锁是通过给索引上 ...
- PMP模拟考试-2
1. Increasing resources on the critical path activities may not always shorten the length of the pro ...
- JBOSS 数据源配置并使用JNDI调用
-- 本文出自sleest (感谢yangjj ^_^) 场景分析: 某天系统的数据库维护方要求进行DG备库容灾演练,要把生产用RAC库模拟宕机并转移至DG备库上,由于是failover而不是swit ...
- Dubbo -- 系统学习 笔记 -- 示例 -- 线程模型
Dubbo -- 系统学习 笔记 -- 目录 示例 想完整的运行起来,请参见:快速启动,这里只列出各种场景的配置方式 线程模型 事件处理线程说明 如果事件处理的逻辑能迅速完成,并且不会发起新的IO请求 ...
- Java 流(Stream)、文件(File)和IO -- Java ByteArrayOutputStream类
Java ByteArrayOutputStream类 字节数组输出流在内存中创建一个字节数组缓冲区,所有发送到输出流的数据保存在该字节数组缓冲区中.创建字节数组输出流对象有以下几种方式. 下面的构造 ...
- Disruptor LMAX学习
http://lmax-exchange.github.io/disruptor/ http://bruce008.iteye.com/blog/1408075 http://code.google. ...
- Splash evaljs() 方法
evaljs() 方法可以执行 JavaScript 代码并返回最后一条 JavaScript 语句的返回结果 function main(splash, args) splash:go(" ...
- Linux命令之乐--wget
常见参数: 参数 作用 -b 后台下载模式. -P 下载到指定目录. -t 最大尝试次数. -c 断点续传 -p 下载页面内所有资源,包括图片.视频等. -r 递归下载 实例1,下载本站的所有文章 ...
- 123、 android Retrofit 介绍和使用(转载)
简单使用:http://blog.csdn.net/bitian123/article/details/51899716 http://blog.csdn.net/duanyy1990/article ...
- 【框架学习】Nancy 框架
Nancy 框架 http://liulixiang1988.github.io/nancy-webkuang-jia.html .是一个轻量级用于构建http相应的web框架: .与mvc类似,有自 ...