博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ3728,The merchant(倍增LCA+分治)
阅读量:4048 次
发布时间:2019-05-25

本文共 2088 字,大约阅读时间需要 6 分钟。

题意:有n个城市,有n-1条边使各个城市相互直接或间接连通,给出一件货物在各城市的价格w[n],然后给出q个询问,每个询问有两个城市s,t,问从s到t的路径上买入卖出货物盈利的最大值。注意:在某个城市买入,只能够在其后经过的城市卖出。

分析:假设询问从城市u到城市v的路径上所能获得的最大盈利值,又设lca为u,v的LCA,则u->v的路径就是u->lca->v,那么最大的盈利值就有可能出现在3种情况:

1.在u->lca中出现;
2.在lca->v中出现;
3.在u->lca->v中出现(即有跨过lca)。
第3种情况是比较容易解决的,我们只要求出lca->v中的最大值max_val,减去u->lca中的最小值min_val,max_val-min_val就是答案,因此对于这种情况我们可以设置ma[i][j],mi[i][j]分别表示:
ma[i][j]:在i结点往上跳2j步到达的结点的路径当中的最大价格;
mi[i][j]:在i结点往上跳2j步到达的结点的路径当中的最小价格。
对于第1,2种情况,我们同样可以考虑分治。以第1种情况为例,设k为u->lca路径当中某个结点,那么u->lca可分解为u->k,k->lca。那么最终答案就同样会有3种情况:
1 .在u->k中出现;
2 .在k->lca中出现;
3 .在u->lca中出现(即跨过结点k)。
仿照第3种情况,我们同样可以用倍增的思想来解决。设置up[i][j]表示:
up[i][j]:在i结点往上跳2j步到达的结点的路径当中,最大的价格差(当然,最大价格出现的位置一定要在最小价格出现的位置之后)。
根据上述分析,不难推出up[i][j]的更新方式:
up[i][j]=max(max(up[i][j-1],up[k][j-1]), ma[k][j]-mi[i][j])
其中k=fa[i][j-1],即在i结点往上跳2j-1步到达的结点。
第2种情况与第3种情况相似,可以设置down[i][j]表示:
down[i][j]:设k为在i结点往上跳2j步到达的结点,down[i][j]为k->i的路径当中,最大的价格差。

代码如下:

#include
#include
#include
#include
#include
#include
using namespace std;typedef long long ll;const int maxn=1e5+5;const int inf=0x3f3f3f3f;int depth[maxn],fa[maxn][20];ll ma[maxn][20],mi[maxn][20];ll up[maxn][20],down[maxn][20];ll w[maxn];bool vis[maxn];vector
G[maxn];inline void read(ll &ret){ char c; while((c=getchar())&&(c>'9'||c<'0')); ret=0; while(c>='0'&&c<='9') ret=ret*10+c-'0', c=getchar();}inline void out(ll x){ if(x>9) out(x/10); putchar(x%10+'0');}void DFS(int u,int pre,int d){ fa[u][0]=pre; ma[u][0]=max(w[u],w[pre]); up[u][0]=max(0ll,w[pre]-w[u]); vis[u]=1; depth[u]=d; if(u!=1) mi[u][0]=min(w[u],w[pre]), down[u][0]=max(0ll,w[u]-w[pre]); else mi[u][0]=w[u], down[u][0]=0; for(int i=0;i
lca中的最小值,同时也会发挥其他作用{ ll ans=0; for(int i=20;i>=0;--i) { if((1<
v中的最大值,同样也会发挥其他作用{ ll ans=0; for(int i=20;i>=0;--i) { if((1<
depth[u]) swap(u,v); int temp=depth[u]-depth[v]; for(int i=0;(1<
<=temp;++i) { if((1<
=0;--i) { if(fa[u][i]!=fa[v][i]) { u=fa[u][i]; v=fa[v][i]; } } return fa[u][0];}int main(){ ll n; read(n); for(int i=1;i<=n;++i) read(w[i]); for(int i=1;i

PS:分治思想有时可以发挥很大的作用。

转载地址:http://vwdci.baihongyu.com/

你可能感兴趣的文章
教育数字智能化能为现有体系带来新的起点
查看>>
媒体广告业如何将内容资产进行高效地综合管理与利用
查看>>
能源化工要怎么管控核心数据
查看>>
媒体广告业如何运用云盘提升效率
查看>>
企业如何运用企业云盘进行数字化转型-实现新发展
查看>>
司法如何运用电子智能化加快现代化建设
查看>>
iSecret&nbsp;1.1&nbsp;正在审核中
查看>>
IOS开发的开源库
查看>>
IOS开发的开源库
查看>>
Jenkins - sonarqube 代码审查
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成(一)
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成 - 单机部署(二)
查看>>
Jenkins + Docker + SpringCloud 微服务持续集成 - 高可用集群部署(三)
查看>>
Golang struct 指针引用用法(声明入门篇)
查看>>
Linux 粘滞位 suid sgid
查看>>
C#控件集DotNetBar安装及破解
查看>>
Winform皮肤控件IrisSkin4.dll使用
查看>>
Winform多线程
查看>>
C# 托管与非托管
查看>>
Node.js中的事件驱动编程详解
查看>>