[POJ3728]The merchant
题目大意:
给你一棵n个结点的带权树,有q组询问,问你从u到v的路径上最大值与最小值的差(最大值在最小值后面)。
思路:
首先考虑路径上合并两个子路径u->t和t->v时的情况。
假设我们已经知道了两个路径的最大值max,最小值min,以及路径上最大值与最小值的差d(最大值在最小值后面),
那么我们最大值和最小值可以直接合并,d=max(d1,d2,max2-max1)。
现在我们用倍增或者树链剖分维护这些东西,再跑一跑LCA即可。
然而我们发现往上跑和往下跑是不一样的,所以我们要维护两种差值up和down,一种是最大值在最小值上,一种是最小值在最大值上。
#include<cstdio>
#include<cctype>
#include<vector>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
const int inf=0x7fffffff;
const int N=,logN=;
int w[N];
std::vector<int> e[N];
inline void add_edge(const int &u,const int &v) {
e[u].push_back(v);
e[v].push_back(u);
}
inline int log2(const float &x) {
return ((unsigned&)x>>&)-;
}
int dep[N],anc[N][logN],max[N][logN],min[N][logN],up[N][logN],down[N][logN];
void dfs(const int &x,const int &par) {
dep[x]=dep[par]+;
anc[x][]=par;
max[x][]=std::max(w[x],w[par]);
min[x][]=std::min(w[x],w[par]);
up[x][]=std::max(w[par]-w[x],);
down[x][]=std::max(w[x]-w[par],);
for(register int i=;i<=log2(dep[x]);i++) {
anc[x][i]=anc[anc[x][i-]][i-];
max[x][i]=std::max(max[x][i-],max[anc[x][i-]][i-]);
min[x][i]=std::min(min[x][i-],min[anc[x][i-]][i-]);
up[x][i]=std::max(std::max(up[x][i-],up[anc[x][i-]][i-]),max[anc[x][i-]][i-]-min[x][i-]);
down[x][i]=std::max(std::max(down[x][i-],down[anc[x][i-]][i-]),max[x][i-]-min[anc[x][i-]][i-]);
}
for(unsigned i=;i<e[x].size();i++) {
const int &y=e[x][i];
if(y==par) continue;
dfs(y,x);
}
}
inline int lca(int x,int y) {
if(dep[x]<dep[y]) std::swap(x,y);
for(register int i=log2(dep[x]);i>=;i--) {
if(dep[anc[x][i]]>=dep[y]) {
x=anc[x][i];
}
}
if(x==y) return x;
for(register int i=log2(dep[x]);i>=;i--) {
if(anc[x][i]!=anc[y][i]) {
x=anc[x][i];
y=anc[y][i];
}
}
return anc[x][];
}
inline int solve(int x,int y) {
const int t=lca(x,y);
int pmaxup=,pminup=inf,pmaxdown=,pmindown=inf,pup=,pdown=;
for(register int i=log2(dep[x]);i>=;i--) {
if(dep[anc[x][i]]>=dep[t]) {
pup=std::max(std::max(pup,up[x][i]),max[x][i]-pminup);
pmaxup=std::max(pmaxup,max[x][i]);
pminup=std::min(pminup,min[x][i]);
x=anc[x][i];
}
}
for(register int i=log2(dep[y]);i>=;i--) {
if(dep[anc[y][i]]>=dep[t]) {
pdown=std::max(std::max(pdown,down[y][i]),pmaxdown-min[y][i]);
pmaxdown=std::max(pmaxdown,max[y][i]);
pmindown=std::min(pmindown,min[y][i]);
y=anc[y][i];
}
}
return std::max(std::max(pup,pdown),pmaxdown-pminup);
}
int main() {
int n=getint();
for(register int i=;i<=n;i++) {
w[i]=getint();
}
for(register int i=;i<n;i++) {
add_edge(getint(),getint());
}
dfs(,);
for(register int q=getint();q;q--) {
const int u=getint(),v=getint();
printf("%d\n",solve(u,v));
}
return ;
}
[POJ3728]The merchant的更多相关文章
- POJ3728 The merchant解题报告
Description There are N cities in a country, and there is one and only one simple path between each ...
- [POJ3728]The merchant(tanrjan_lca + DP)
传送门 比着题解写还错... 查了两个小时没查出来,心态爆炸啊 以后再查 ——代码(WA) #include <cstdio> #include <cstring> #incl ...
- POJ3728 THE MERCHANT LCA RMQ DP
题意简述:给定一个N个节点的树,1<=N<=50000 每个节点都有一个权值,代表商品在这个节点的价格.商人从某个节点a移动到节点b,且只能购买并出售一次商品,问最多可以产生多大的利润. ...
- poj3728 The merchant[倍增]
给一棵点带权树,$q$次询问,问树上$x$到$y$路径上,两点权之差(后面的减去前面的)的最大值. 这个是在树链上找点,如果沿路径的最小值在最大值之前出现那肯定答案就是$maxx-minx$,但是反之 ...
- [最近公共祖先] POJ 3728 The merchant
The merchant Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 4556 Accepted: 1576 Desc ...
- POJ 3278 The merchant
传送门 Time Limit: 3000MS Memory Limit: 65536K Description There are N cities in a country, and there i ...
- poj 3728 The merchant(LCA)
Description There are N cities in a country, and there is one and only one simple path between each ...
- ThoughtWorks Merchant's Guide To The Galaxy
ThoughtWorks笔试题之Merchant's Guide To The Galaxy解析 一.背景 在某网站上看到ThoughtWorks在武汉招人,待遇在本地还算不错,就投递了简历.第二天H ...
- [POJ 3728]The merchant
Description There are N cities in a country, and there is one and only one simple path between each ...
随机推荐
- Bagging和Boosting 概念及区别(转)
Bagging和Boosting都是将已有的分类或回归算法通过一定方式组合起来,形成一个性能更加强大的分类器,更准确的说这是一种分类算法的组装方法.即将弱分类器组装成强分类器的方法. 首先介绍Boot ...
- FindQQByProcess
看网上有许多通过进程寻找QQ号的例子,看了一下,里面涉及的知识点还是比较多,但网上的兼容性不太好,而且没有给出匹配字符的来源,所以自己动手写了一下,顺便给出一些我调试的结果. #include &qu ...
- Redis 3.0 编译安装
Redis 3.0 编译安装 http://www.xuchanggang.cn/archives/991.html
- C基础 常用设计模式粗解
引言 面向对象, 设计模式是现代软件开发基石. C的面向过程已经很简洁, 但不代表C就没有面向对象.(libuv框架中C面向对象用的很多) 因为思想是互通的.全当熟悉一下那些常用的设计模式.先假定有一 ...
- python的IDLE界面回退代码语句
Alt+P回退到IDLE中之前输入的代码语句 Alt+N可以移至下一个代码语句
- java web 资源文件读取
前提:假设web应用test(工程名) webapps下面有一资源文件test.html 规则:在获取资源时一般使用的是相对路径,以符号/开头,而 / 代表什么取决于这个地址给谁使用.服务器使用时,/ ...
- popup menu案例,无说明只代码
效果图: 布局文件, 展示列表的容器 <?xml version="1.0" encoding="utf-8"?> <LinearLayout ...
- [New Learn]被嫌弃的app的一生
1.简介 为什么叫被嫌弃的app的一生?致敬电影<被嫌弃的松子的一生>. 自学IOS东一锄西一镐的总感觉没有一个总的概念,还是多看看官网吧,先看一下一个app的整个生命周期,本文主要是翻译 ...
- Cent os FTP配置
原文:http://www.aicoffees.com/itshare/412261137.html
- linux命令(10):ps命令
1.查看mysql进程数: ps -ef | grep "mysql" | grep -v "grep" | wc –l 2.监控CPU状态:ps –au 3. ...