POJ 3728 The merchant

题意好像不清楚:

给定一棵 nn 个点的树,每个点有点权 valival_i,现在有 qq 个询问,每次询问给出 u,vu,v,设 uuvv 的路径上的点编号为 a1,a2alena_1,a_2\cdots a_{len},求 max1x<ylenvalayvalax\max\limits_{1 \le x < y\le len}{val_{a_y}-val_{a_x}}

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

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

发现这个题没有修改,应该是静态的东西,思考一下有什么东西像这个分治结构,看完题解后发现就是倍增,具体来讲就是我们直接维护 upu,jup_{u,j} 表示从 uu 走到他的 2j12^j-1 级祖先的答案,downu,jdown_{u,j} 表示从 uu2j12^j-1 级祖先走到 uu 的答案,fu,jf_{u,j} 表示 uu2j2^j 级祖先是谁,mxu,jmx_{u,j} 表示 uu 到他的 2j12^j-1 级祖先中权值最大值,mnmn 为最小值。

在计算 upup 的时候是类似于 upu,j=max({upu,j1,upfu,j1,j1,mxfu,j1,j1mnu,j1})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}\}),这玩意就是类似于分治区间为 uujj 级祖先,然后分治成 uuj1j-1 级祖先和 fu,j1f_{u,j-1}j1j-1 级祖先两部分,然后最后的就是当前区间跨过分治中点的答案, downdown 是同理的。

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#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;
}

POJ 3728 The merchant
http://lnyxqwq.github.io/2023/08/15/POJ 3728 The merchant/
作者
lnyx
发布于
2023年8月15日
许可协议