题目大意:
  给你一棵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的更多相关文章

  1. POJ3728 The merchant解题报告

    Description There are N cities in a country, and there is one and only one simple path between each ...

  2. [POJ3728]The merchant(tanrjan_lca + DP)

    传送门 比着题解写还错... 查了两个小时没查出来,心态爆炸啊 以后再查 ——代码(WA) #include <cstdio> #include <cstring> #incl ...

  3. POJ3728 THE MERCHANT LCA RMQ DP

    题意简述:给定一个N个节点的树,1<=N<=50000 每个节点都有一个权值,代表商品在这个节点的价格.商人从某个节点a移动到节点b,且只能购买并出售一次商品,问最多可以产生多大的利润. ...

  4. poj3728 The merchant[倍增]

    给一棵点带权树,$q$次询问,问树上$x$到$y$路径上,两点权之差(后面的减去前面的)的最大值. 这个是在树链上找点,如果沿路径的最小值在最大值之前出现那肯定答案就是$maxx-minx$,但是反之 ...

  5. [最近公共祖先] POJ 3728 The merchant

    The merchant Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 4556   Accepted: 1576 Desc ...

  6. POJ 3278 The merchant

    传送门 Time Limit: 3000MS Memory Limit: 65536K Description There are N cities in a country, and there i ...

  7. poj 3728 The merchant(LCA)

    Description There are N cities in a country, and there is one and only one simple path between each ...

  8. ThoughtWorks Merchant's Guide To The Galaxy

    ThoughtWorks笔试题之Merchant's Guide To The Galaxy解析 一.背景 在某网站上看到ThoughtWorks在武汉招人,待遇在本地还算不错,就投递了简历.第二天H ...

  9. [POJ 3728]The merchant

    Description There are N cities in a country, and there is one and only one simple path between each ...

随机推荐

  1. linux下守护进程的创建

    最近在学习linux c编程 看到了守护进程的创建,感觉很好玩, 测试环境ubuntu 15.04 下面贴出测试代码 #include <stdio.h> #include <std ...

  2. linux编程之共享内存

    linux 进程间通信(IPC)包括3种机制:消息队列.信号量.共享内存.消息队列和信号量均是内核空间的系统对象,经由它们 的数据需要在内核和用户空间进行额外的数据拷贝:而共享内存和访问它的所有应用程 ...

  3. 增大dma的分配

    前言 项目中需要通过驱动与fpga通讯,获取fpga往内存里写的数据.因为数据量比较大,需要驱动分配600多M的内存给fpga来写数据,且因为是与fpga通讯,需要连续的内存,还得是uncached的 ...

  4. 自动化测试===Httprunner测试框架介绍

    项目地址: https://github.com/HttpRunner/HttpRunner 中文手册: http://cn.httprunner.org/ 首先是环境搭建: pip install ...

  5. MySQL多线程复制故障(slave_pending_jobs_size_max)

    MySQL多线程复制故障(slave_pending_jobs_size_max) http://www.xuchanggang.cn/archives/1079.html

  6. 81.Search in Rotated Sorted Array II---二分变形

    题目链接 题目大意:与33题类似,只是这里数组中有重复数值. 法一:解法与33题类似,只是这里要处理1,3,1,1,1这种情况,即有重复值时,mid与left和right都相等时,可以采用right- ...

  7. 1000: 恶意IP 课程作业

    1000: 恶意IP Time Limit: 1 Sec  Memory Limit: 16 MB Description Water同学最近好不容易学会了用Tornado建起一个个人的Website ...

  8. English——Unit 1

    meditate  v.沉思,冥想:考虑,谋划 medtiation   n.沉思,冥想:深思熟虑 medium elaborate   adj.精心制作的,详尽的,复杂的:v.精心制作:详述(计划, ...

  9. leetcode 之Remove Nth Node From End of List(19)

    这题比较简单,方法有很多.其中一种比较有意思的做法是设置两个指针,一个先走n步,然后再一起走.一个到了末尾,另一个也就确定了要删除元素的位置. ListNode *removeNthFromEnd(L ...

  10. 机器学习方法(五):逻辑回归Logistic Regression,Softmax Regression

    欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld. 技术交流QQ群:433250724,欢迎对算法.技术.应用感兴趣的同学加入. 前面介绍过线性回归的基本知识, ...