题目大意:
  给你一棵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. Python switch-case语句的实现 -- 字典模拟实现

    static void print_asru_status(int status, char *label) { char *msg = NULL; switch (status) { : msg = ...

  2. ImageView设置边框 以及内部图片居中显示 在AndroidStudio中添加shape.xml文件

    效果如图 边框设置:shape文件 <shape xmlns:android="http://schemas.android.com/apk/res/android"> ...

  3. Ubuntu安装pip

    首先打开终端 在终端输入:sudo apt-get install python-pip python-dev build-essential [+] 如果需要在Python3下安装pip,那么在py ...

  4. python中的argparse模块

    argparse干什么用的? 答:参数设置,比如python demo.py -h 诸如此类的. 开始学习这个模块: parser = argparse.ArgumentParser() #使用这个模 ...

  5. postman测试express restful接口

    安装express及postman var express = require('express') var app = express(); var calculation = require('. ...

  6. Python学习笔记 - day8 - 异常

    异常 在程序运行过程中,总会遇到各种各样的错误.有的错误是程序编写有问题造成的,比如本来应该输出整数结果输出了字符串,有的错误是用户输入造成的,比如让用户输入email地址,结果得到一个空字符串,这种 ...

  7. DXEditingRow的错误原因

    原因之一:例如commbox理由id这一列但是数据库表中没有的话就会报这个错误

  8. XML 约束 (DTD和 schema)

    book.DTD 如下: <?xml version="1.0" encoding="UTF-8" ?> <schema xmlns=&quo ...

  9. Java AQS学习

    参考原文: Java并发之AQS详解 <Java并发编程的艺术> AQS 概述 AQS简介 AQS(AbstractQueuedSynchronizer)就是一个抽象的队列同步器,它是用来 ...

  10. poj 3404&&poj1700(贪心)

    Bridge over a rough river Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4143   Accept ...