题目大意:
  给你一棵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. hadoop2.4.1伪分布式环境搭建

    注意:所有的安装用普通哟用户安装,所以首先使普通用户可以以sudo执行一些命令: 0.虚拟机中前期的网络配置参考: http://www.cnblogs.com/qlqwjy/p/7783253.ht ...

  2. 纠结于arch+xfce还是xubuntu

    现在用的是ubuntu gnome版 http://www.tuicool.com/articles/6r22eyU 现在纠结于arch+xfce还是xubuntu,因为不想在gnome下面搞什么美化 ...

  3. FastDFS介绍和配置过程

    由于网站使用nfs共享方式保存用户上传的图片,附件等资料,然后通过apache下载的方式供用户访问,在网站架构初期,使用这种简单的方式实现了静态资源的读写分离,但随着网站数据量的增加,图片服务器渐渐成 ...

  4. [Leetcode Week12]Unique Paths

    Unique Paths 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/unique-paths/description/ Description A ...

  5. net_device->uc_promisc

    如果设备不支持单播过滤,并且要监听多个单播地址时,就要使用net_device->uc_count和net_device->uc_promisc来设置混杂模式,具体见__dev_set_r ...

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

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

  7. C# 网络编程小计 20150202

    在学习网络Socket编程之前必须得学会多线程编程,这个是经常会用的到 可参考:http://www.cnblogs.com/GIS_zhou/articles/1839248.html System ...

  8. MySQL的读写分离---主从复制、主主复制

    1.复制是基于BinLog日志 存在三种日志格式:Statement:存储Sql语句,存储日志量是最小的.有可能复制不一致Row:存储event数据,存储日志量大,但是不能很直接进行读取:Mixed: ...

  9. django使用用户名或手机号码登录

    django有自己的认证系统,会自动根据用户名和密码进行验证.如果需要使用用户名或手机登录的话,需要重写django的认证后台,并且设置到配置文件中. 重写django的认证后台 class User ...

  10. CentOS 7下OpenLDAP编译安装及配置

    一.环境 Server:基于CentOS-7-x86_64-1511 Server IP: 172.18.12.203 二.软件获取 OpenLDAP OpenLDAP官网下载地址:http://ww ...