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 ...
随机推荐
- DTD与模式
摘要 我们在制作页面时必须要测的就是IE浏览器,毕竟IE浏览器市场占有率还是很高.随着HTML5的流行,可能项目要求兼容IE最低版本为IE8或者更高,但是还是有很多项目兼容IE低版本.所以我们经常会碰 ...
- js 或 且 非
给定 x=6 以及 y=3,下表解释了逻辑运算符: 运算符 描述 例子 && and (x < 10 && y > 1) 为 true || or (x== ...
- SpringMVC由浅入深day01_5注解的处理器映射器和适配器
5 注解的处理器映射器和适配器 在spring3.1之前使用org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandle ...
- Dubbo -- 系统学习 笔记 -- 示例 -- 多协议
Dubbo -- 系统学习 笔记 -- 目录 示例 想完整的运行起来,请参见:快速启动,这里只列出各种场景的配置方式 多协议 可以自行扩展协议,参见:协议扩展 (1) 不同服务不同协议 比如:不同服务 ...
- NetBpm 组织架构(4)
大牛的杰作,赞一个 转自:NetBPM工作流的架构设计及实现浅析 读前的话:由于本文涉及内容颇多,若有地方读来不很明白,建议先跳过,整体上有个认识后,再回过头来理解.作者认识有限,若有错误,欢迎斧正: ...
- ajax简单手写了一个猜拳游戏
使用ajax简单写一个猜拳游戏 HTML代码 <!DOCTYPE HTML> <html lang="en-US"> <head> <me ...
- JavaScript之with语句
with 语句的作用是将代码的作用域设置到一个特定的对象中. with可以简化多次写同一个对象的工作, 示例: var o={name:'a',age:25,sex:'male'} var na=o. ...
- zabbix添加对tomcat线程池的监控
在zabbix模板中添加以下监控项: 可以参考文档:http://www.fblinux.com/?p=616
- VS调试DLL项目代码
如果DLL有对应的lib文件,并且dll工程和调用它的exe属于同一个解决方案,直接打断点调试就可以.例如OSG解决方案中的例子程序可以直接调试osgUtil模块的代码. 如果A.exe项目和A.dl ...
- [XPath] XPath 与 lxml (三)XPath 坐标轴
本章我们将沿用上一章的 XML 示例文档. XPath 坐标轴 坐标轴用于定义当对当前节点的节点集合. 坐标轴名称 含义 ancestor 选取当前节点的所有先辈元素及根节点. ancestor-or ...