首页 > 其他分享 >POJ 3728 The merchant

POJ 3728 The merchant

时间:2023-07-05 10:47:51浏览次数:49  
标签:merchant Log val int max dep POJ ans 3728

题意好像不清楚:

给定一棵 \(n​\) 个点的树,每个点有点权 \(val_i​\),现在有 \(q​\) 个询问,每次询问给出 \(u,v​\),设 \(u​\) 到 \(v​\) 的路径上的点编号为 \(a_1,a_2\cdots a_{len}​\),求 \(\max\limits_{1 \le x < y\le len}{val_{a_y}-val_{a_x}}​\)。

因为 \(x,y\) 有顺序限制,所以不好直接做,最直观的思路应该就是对于每个询问分治,这样我们就把顺序限制干掉了,但是直接分治的复杂度是 \(O(qn\log n)\) 的,直接寄。

然后我就不会做了。013@2x.gif (56×56) (emojiall.com)

发现这个题没有修改,应该是静态的东西,思考一下有什么东西像这个分治结构,看完题解后发现就是倍增,具体来讲就是我们直接维护 \(up_{u,j}​\) 表示从 \(u​\) 走到他的 \(2^j-1​\) 级祖先的答案,\(down_{u,j}​\) 表示从 \(u​\) 的 \(2^j-1​\) 级祖先走到 \(u​\) 的答案,\(f_{u,j}​\) 表示 \(u​\) 的 \(2^j​\) 级祖先是谁,\(mx_{u,j}​\) 表示 \(u​\) 到他的 \(2^j-1​\) 级祖先中权值最大值,\(mn​\) 为最小值。

在计算 \(up\) 的时候是类似于 \(up_{u,j}=\max(\{up_{u,j-1},up_{f_{u,j-1},j-1},mx_{f_{u,j-1},j-1}-mn_{u,j-1}\})\),这玩意就是类似于分治区间为 \(u\) 到 \(j\) 级祖先,然后分治成 \(u\) 到 \(j-1\) 级祖先和 \(f_{u,j-1}\) 到 \(j-1\) 级祖先两部分,然后最后的就是当前区间跨过分治中点的答案, \(down\) 是同理的。

最后统计答案也是类似与分治的合并,跟上面的一样。

code:(POJ 只支持 C++98 074@2x.gif (56×56) (emojiall.com)

#include<cstdio>
#include<iostream>
#include<vector>
#define pb push_back
using namespace std;
const int INF=1e9+7;
const int N=5e4+7,Log=16;
int n;
int val[N];
int up[N][Log],down[N][Log],mx[N][Log],mn[N][Log],f[N][Log];
int dep[N];
vector<int>g[N];
inline void dfs(int u,int fa){
	dep[u]=dep[fa]+1;
	f[u][0]=fa,mx[u][0]=mn[u][0]=val[u];
	for(int j=1;j<Log;j++){
		f[u][j]=f[f[u][j-1]][j-1];
		mx[u][j]=max(mx[u][j-1],mx[f[u][j-1]][j-1]);
		mn[u][j]=min(mn[u][j-1],mn[f[u][j-1]][j-1]);
		up[u][j]=max(up[u][j-1],max(up[f[u][j-1]][j-1],mx[f[u][j-1]][j-1]-mn[u][j-1]));
		down[u][j]=max(down[u][j-1],max(down[f[u][j-1]][j-1],mx[u][j-1]-mn[f[u][j-1]][j-1]));
	}
	for(int i=0;i<g[u].size();i++){
		int v=g[u][i];
		if(v==fa) continue;
		dfs(v,u);
	}
}
inline int lca(int u,int v){
	if(dep[u]<dep[v]) swap(u,v);
	for(int j=Log-1;j>=0;j--){
		if(dep[f[u][j]]>=dep[v]) u=f[u][j];
	}
	if(u==v) return u;
	for(int j=Log-1;j>=0;j--){
		if(f[u][j]!=f[v][j]) u=f[u][j],v=f[v][j];
	}
	return f[u][0];
}
int main(){
#ifndef ONLINE_JUDGE
	freopen("in.in","r",stdin);
	freopen("out.out","w",stdout);
#endif
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&val[i]);
	for(int i=1;i<n;i++){
		int u,v; scanf("%d%d",&u,&v);
		g[u].pb(v),g[v].pb(u);
	}
	dfs(1,0);
	int q; scanf("%d",&q);
	while(q--){
		int u,v; scanf("%d%d",&u,&v);
		int ans=0,anc=lca(u,v),MX=0,MN=INF;
		for(int j=Log-1;j>=0;j--){
			if(dep[f[u][j]]>=dep[anc]) ans=max(ans,max(up[u][j],mx[u][j]-MN)),MN=min(MN,mn[u][j]),u=f[u][j]; 
		}
		ans=max(ans,val[anc]-MN),MN=min(MN,val[anc]);
		for(int j=Log-1;j>=0;j--){
			if(dep[f[v][j]]>=dep[anc]) ans=max(ans,max(down[v][j],MX-mn[v][j])),MX=max(MX,mx[v][j]),v=f[v][j];
		}
		ans=max(ans,MX-val[anc]),MX=max(MX,val[anc]);
		printf("%d\n",max(ans,MX-MN));
	}
	return 0;
}

标签:merchant,Log,val,int,max,dep,POJ,ans,3728
From: https://www.cnblogs.com/lnyx/p/17527871.html

相关文章

  • poj 3233(矩阵快速幂)
    题意:给出一个矩阵A和数字k,要求出矩阵S=A+A^2+A^3+…+A^k。题解:首先A^x可以计算,然后需要折半计算,比如s(k)=(1+A^(k/2))*s(k/2),但k的奇偶不同需要分情况。#include<stdio.h>#include<string.h>constintN=35;structMat{intg[N][N];};intn,k,m......
  • 分治/质因数分解 POJ1845 求pow(a, b)的所有约数之和
    //POJ1845求pow(a,b)的所有约数之和//方法:1,分解质因数,将a分解成p1^k1*p2^k2^...*pn^kn//2,那么pow(a,b)为p1^(k1*b)*p2^(k2*b)^...*pn^(kn*b)//3,对于单独的pi^(ki*b),他所有的约数为(1,pi,pi^2,pi^3.....pi^(ki*b));//4,那么整个式子来说,pow(a,......
  • VO,DTO,BO,POJO,PO的概念介绍
     po:1.po:popersistentobject持久对象,持久对象的意思指的是可以从内存中存储到关系型数据库中。2.因此一个po对应的数据库中的每一条记录。pojo:1.pojo:plainordinaryjavaobject无规则简单java对象,对应的是我们代码中的实体类。2.pojo持久化之后就是po了,可以看作一个中......
  • POJ2117 Electricity 题解 tarjan点双连通分量 割点
    题目链接:http://poj.org/problem?id=2117题目大意:给定一个由\(n\)个点\(m\)解题思路:tarjan,判断\(u\)的子节点有几个\(v\)满足\(low[v]\gedfn[u]\)就是答案,但是同时如果\(u\)不是这个dfs树的根节点,个数还要加\(1\)。示例程序1(C++11,POJ不支持):#include<bits/stdc++.h>......
  • POJ2117 Electricity 题解 tarjan点双连通分量 割点
    题目链接:http://poj.org/problem?id=2117题目大意:给定一个由\(n\)个点\(m\)条边构成的无向图,请你求出该图删除一个点之后,连通块最多有多少。解题思路:tarjan,判断\(u\)的子节点有几个\(v\)满足\(low[v]\gedfn[u]\)就是答案,但是同时如果\(u\)不是这个dfs树的根节......
  • POJ 3131 - Cubic Eight-Puzzle
    很明显可以看出是一道搜索题。首先考虑\(bfs\),第一种思路是每次从给定的初始状态都进行一次\(bfs\),直到\(30\)停止。然后我们发现,初始状态根据一开始空格的位置不同,一共只有\(9\)种。而一个状态可以用空格的位置、所有位置上方的颜色、所有位置左方的颜色唯一确定,一共\(6^......
  • 深入理解 DAO,DTO,DO,VO,AO,BO,POJO,PO,Entity,Model,View 各个模型对象的概念
    参考文档:https://blog.csdn.net/SR02020/article/details/105821816 深入理解DAO,DTO,DO,VO,AO,BO,POJO,PO,Entity,Model,View的概念DAO(DataAccessObject)数据访问对象DTO(DataTransferObject)数据传输对象DO(DomainObject)领域对象VO(ViewObject)视图模型AO(ApplicationObject)应用对象......
  • poj-2823 Sliding Window(单调队列)
    原题链接SlidingWindowTimeLimit: 12000MS MemoryLimit: 65536KTotalSubmissions: 54929 Accepted: 15814CaseTimeLimit: 5000MSDescriptionAnarrayofsize n ≤106 isgiventoyou.Thereisaslidingwindowofsize k whichismoving......
  • POJ 1459 Power Network(最大流)
    题意:第一眼看到这题目觉得神题啊...其实题目给的s[i]压根不用管的....总共有n个结点,其中有发电站np个、用户nc个和调度器n-np-nc个三种节点以及M条电线(用于传输电流的),每个发电站有一个最大发电量,每个用户有个最大接受电量,现在有m条有向边,边有一个最大的电流量,表示最多可以流出这......
  • POJ1787
    POJ1787一开始还没看多重背包…以为是完全背包加个限制条件,然后想了好久没想不出,看了下背包九讲..看到多重背包可是也没什么思路…后来搜了一下题解…豁然开朗dp[j]表示j块钱最多由多少块硬币组成,path[j]表示上一次最多有多少块构成的j块钱,used[j]表示j块钱时,已经放了......