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

算法分析:显然任意两个城市之间的路径是唯一的,商人有方向地从起点移动到终点。询问这条路径上任意两点权值之差最大为多少,且要保证权值较大的节点在路径上位于权值较小的节点之后。

暴力的方法是显而易见的,只要找到两个点的深度最深的公共祖先,就等于找到了这条路径,之后沿着路径走一遍即可找到最大的利润,然而无法满足50000的数据规模。

首先考虑高效寻找LCA(公共祖先)的方法。记录ance[i][j]为节点i向上走2^j步到达的某个祖先。可以简单地列出方程 ance[i][j]=ance[ance[i][j-1]][j-1];于是找到了高效构建的方法。

每次寻找LCA 首先将两个节点通过swim(a,b)函数转移到同一深度,然后每次找一个最小的j使得ance[a][j]==ance[b][j] 之后将节点a赋值为ance[a][j-1] 直到j=0就找到了两者的LCA

现在我们已经找到了高效寻找LCA的方法,假设我们知道节点a到LCA的最小值minp[],LCA到节点b的最大值maxp[],

以及买卖地点全在LCA之前可以获得的最大利润maxi[] 以及买卖地点全在LCA之后可以获得的最大利润maxI[] 显然就得到了最后的答案。 维护这些数据的方式类似于维护ance数组的方式,DP方程也很好列出, 这里就不给出了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
using namespace std;
const int maxn=50000+10;
vector<int>po[maxn];
int dep[maxn],ance[maxn][17],maxp[maxn][17],minp[maxn][17],maxi[maxn][17],maxI[maxn][17],price[maxn],n,fa[maxn];
bool vis[maxn];
int max(int a,int b)
{
if(a>b)return a;
else return b;
}
int min(int a,int b)
{
if(a>b)return b;
else return a;
}
queue<int> q;
void BFS_build()
{
memset(vis,0,sizeof(vis)); q.push(1);
fa[1]=1;
dep[1]=1;
vis[1]=true;
while(!q.empty())
{
int np=q.front();q.pop();
ance[np][0]=fa[np];
maxp[np][0]=max(price[np],price[fa[np]]);
minp[np][0]=min(price[np],price[fa[np]]);
if(price[np]<price[fa[np]])maxi[np][0]=price[fa[np]]-price[np];
else maxi[np][0]=0;
if(price[np]>price[fa[np]])maxI[np][0]=price[np]-price[fa[np]];
else maxI[np][0]=0;
for(int i=1;i<=16;i++)//倍增DP方程
{
ance[np][i]=ance[ance[np][i-1]][i-1];
maxp[np][i]=max(maxp[np][i-1],maxp[ance[np][i-1]][i-1]);
minp[np][i]=min(minp[np][i-1],minp[ance[np][i-1]][i-1]);
int a=maxi[np][i-1],b=maxi[ance[np][i-1]][i-1],c=0;
c=maxp[ance[np][i-1]][i-1]-minp[np][i-1];
maxi[np][i]=max(max(a,b),c);
a=maxI[np][i-1];b=maxI[ance[np][i-1]][i-1];c;
c=maxp[np][i-1]-minp[ance[np][i-1]][i-1];
maxI[np][i]=max(max(a,b),c);
if(ance[np][i]==1)break;
}
for(int i=0;i<po[np].size();i++)
{
int nv=po[np][i];
if(vis[nv])continue;
fa[nv]=np;
dep[nv]=dep[np]+1;
q.push(nv);
vis[nv]=true;
}
}
}
int ia,ib,mi,ma;
int ancest;
void swim(int &a,int &b)
{
if(dep[a]==dep[b])return ;
while(dep[a]>dep[b])
{
int i;
for(i=0;i<=16;i++)
{
if(pow(2,i)+dep[b]>dep[a])break;
}
ia=max(max(ia,maxi[a][i-1]),maxp[a][i-1]-mi);
mi=min(mi,minp[a][i-1]);
a=ance[a][i-1];
}
while(dep[a]<dep[b])
{
int i;
for(i=0;i<=16;i++)
{
if(pow(2,i)+dep[a]>dep[b])break;
}
ib=max(max(ib,maxI[b][i-1]),ma-minp[b][i-1]);
ma=max(ma,maxp[b][i-1]);
b=ance[b][i-1];
}
}
int solve(int a,int b)
{
ia=0;ib=0;mi=price[a];ma=price[b];
swim(a,b);
if(a==b)return max(max(ia,ib),ma-mi); while(true)
{
int i;
for(i=0;i<=16;i++)
{
if(ance[a][i]==ance[b][i])break;
}
if(i==0)
{
ancest=ance[a][0];
ia=max(ia,price[ancest]-mi);
ib=max(ib,ma-price[ancest]);
mi=min(mi,price[ancest]);
ma=max(ma,price[ancest]);
return max(max(ia,ib),ma-mi);
}
else
{
ia=max(max(ia,maxi[a][i-1]),maxp[a][i-1]-mi);
ib=max(max(ib,maxI[b][i-1]),ma-minp[b][i-1]);
mi=min(mi,minp[a][i-1]);
ma=max(ma,maxp[b][i-1]);
a=ance[a][i-1];b=ance[b][i-1];
}
} }
int main()
{freopen("t.txt","r",stdin);
scanf("%d",&n); for(int i=1;i<=n;i++)
scanf("%d",&price[i]);
for(int i=1;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
po[a].push_back(b);po[b].push_back(a);
}
BFS_build();
int p;
scanf("%d",&p);
for(int i=1;i<=p;i++)
{
int a,b;
scanf("%d%d",&a,&b);
printf("%d\n",solve(a,b));
}
return 0;
}

  这个题目似乎是北大月赛的题目,不得不佩服他们题目的质量,渣校只能仰望了。

POJ3728 THE MERCHANT LCA RMQ DP的更多相关文章

  1. POJ3728 LCA RMQ DP

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

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

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

  3. 【Homework】LCA&RMQ

    我校是神校,作业竟然选自POJ,难道不知道“珍爱生命 勿刷POJ”么? 所有注明模板题的我都十分傲娇地没有打,于是只打了6道题(其实模板题以前应该打过一部分但懒得找)(不过感觉我模板还是不够溜要找个时 ...

  4. POJ 1470 Closest Common Ancestors(LCA&RMQ)

    题意比较费劲:输入看起来很麻烦.处理括号冒号的时候是用%1s就可以.还有就是注意它有根节点...Q次查询 在线st算法 /*************************************** ...

  5. CDOJ 92 Journey(LCA&RMQ)

    题目连接:http://acm.uestc.edu.cn/#/problem/show/92 题意:给定一棵树,最后给加一条边,给定Q次查询,每次查询加上最后一条边之后是否比不加这条边要近,如果近的话 ...

  6. POJ3417 LCA+树dp

    http://poj.org/problem?id=3417 题意:先给出一棵无根树,然后下面再给出m条边,把这m条边连上,然后每次你能毁掉两条边,规定一条是树边,一条是新边,问有多少种方案能使树断裂 ...

  7. 算法详解(LCA&RMQ&tarjan)补坑啦!完结撒花(。◕ˇ∀ˇ◕)

    首先,众所周知,求LCA共有3种算法(树剖就不说了,太高级,以后再学..). 1.树上倍增(ST表优化) 2.RMQ&时间戳(ST表优化) 3.tarjan(离线算法)不讲..(后面补坑啦!) ...

  8. POJ 2763 (LCA +RMQ+树状数组 || 树链部分) 查询两点距离+修改边权

    题意: 知道了一颗有  n 个节点的树和树上每条边的权值,对应两种操作: 0 x        输出 当前节点到 x节点的最短距离,并移动到 x 节点位置 1 x val   把第 x 条边的权值改为 ...

  9. poj3728之离线LCA+dp思想/RMQ+LCA(非常好的题目)

    题意很简单 给一个树(n < 5w) 每个点有个权值,代表商品价格 若干个询问(5w) 对每个询问,问的是从u点走到v点(简单路径),商人在这个路径中的某点买入商品,然后在某点再卖出商品,   ...

随机推荐

  1. 改进后的向量空间模型(VSM)

    我们採用更加形式化的定义,并採用稍大一些的样例来展示怎样使用基于数据集频率的权重.相应于一个给定的词项,其权重使用IDF(逆文档频率)来计算. 为了给每篇文档建立一个相应的向量,能够考虑例如以下定义. ...

  2. PHP如何学习?

    PHP 的学习,可以归纳为三个类型:      语言的基础语法学习,这些是 ifelse, while, switch, class, function, trait 等:  内置函数/类学习,这 ...

  3. android客户端向服务器端验证登陆方法的实现2

    一.在上一篇文章中,我只是提到了其中一种方法来实现登陆 大家可以参见: http://www.apkbus.com/android-45004-1-1.html      android获取web服务 ...

  4. DataSource是什么

    public interface DataSource 该工厂用于提供到此 DataSource 对象表示的物理数据源的连接.作为 DriverManager(二者区别:http://tobylxy. ...

  5. xhtml三种元素类型

    xhtml三种元素类型:块级元素/内联元素/可变元素 块级元素:独占一行.可自定义自己的宽度和高度.作为其他元素的容器,可容纳其他内联元素和块级元素,喻做一个盒子.内联元素:始终以行内逐个显示.不能设 ...

  6. 《后会无期》票房赶超《小时代3》 大数据解读韩寒VS四娘之争

    7月25日.韩寒导演的处女作<后会无期>零点首映,而郭四娘导演的<小时代3:刺金时代>比<后会无期>早上映一周.也就是7月17日正式公映,韩寒与四娘之间向来不缺乏话 ...

  7. [转]FTP服务器搭建

    下面先说第一中方法: 1.在win7上先开启ftp服务:这里点击确定后,可能会要等一会儿,完成后有时系统会提示重启 2.打开   计算机-->管理-->   在这里我们可以看见刚刚添加的服 ...

  8. vue项目结构设计

    感觉这个写的挺详细的,要详细了解可以看这个→ 结构详细介绍 vue项目结构图: 简单介绍: build目录是一些webpack的文件,配置参数什么的,一般不用动 config是vue项目的基本配置文件 ...

  9. kubernetes对象之Ingress

    系列目录 概述 向外网暴露集群内服务,以使客户端能够访问,有以下几种方法,本文重点描述Ingress. LoadBalancer LoadBalancer一般由云服务供应商提供或者用户自定义,运行在集 ...

  10. 浅谈 SOAP

    http://www.ibm.com/developerworks/cn/xml/x-sisoap/ 本文对 SOAP 作了一个初步介绍,给出几个简单示例:接着比较 CORBA,DCOM/COM 与 ...