<倍增lca>codevs 3305 水果姐逛水果街Ⅱ
2017-09-25 16:53
411 查看
题目链接:http://codevs.cn/problem/3305/
–要先求两点的lca,再从x,y分别跳到lca的过程中记录答案,而不是在求lca的过程中,那样没有办法记录答案
–ans1[x][i]表示从x到第2^i个父亲的答案
–ans2[x][i]表示从第2^i个父亲到x的答案
–要先求两点的lca,再从x,y分别跳到lca的过程中记录答案,而不是在求lca的过程中,那样没有办法记录答案
–ans1[x][i]表示从x到第2^i个父亲的答案
–ans2[x][i]表示从第2^i个父亲到x的答案
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> using namespace std; const int maxn=200000+10,inf=100000000+10; int n,m,cnt,ans; int v[maxn],fist[maxn],nxt[maxn<<1],deep[maxn]; int fa[maxn][21],maxx[maxn][21],minn[maxn][21],ans1[maxn][21],ans2[maxn][21]; //ans1:x-->i,ans2:i-->x struct hh { int f,t; }e[maxn<<1]; void done() { for(int x=1;x<=n;++x) for(int i=1;i<=log2(n);++i) { fa[x][i]=fa[fa[x][i-1]][i-1]; maxx[x][i]=max(maxx[x][i-1],maxx[fa[x][i-1]][i-1]); minn[x][i]=min(minn[x][i-1],minn[fa[x][i-1]][i-1]); ans1[x][i]=max(maxx[fa[x][i-1]][i-1]-minn[x][i-1],max(ans1[x][i-1],ans1[fa[x][i-1]][i-1])); ans2[x][i]=max(maxx[x][i-1]-minn[fa[x][i-1]][i-1],max(ans2[x][i-1],ans2[fa[x][i-1]][i-1])); } } void dfs(int f,int t) { deep[t]=deep[f]+1; fa[t][0]=f; maxx[t][0]=max(v[f],v[t]); minn[t][0]=min(v[f],v[t]); ans1[t][0]=v[f]-v[t]; ans2[t][0]=v[t]-v[f]; if(ans1[t][0]<0) ans1[t][0]=0; if(ans2[t][0]<0) ans2[t][0]=0; for(int i=fist[t];i!=-1;i=nxt[i]) if(e[i].t!=f) dfs(t,e[i].t); } void build(int f,int t) { e[++cnt]=(hh){f,t}; nxt[cnt]=fist[f]; fist[f]=cnt; } int lca(int x,int y) { if(deep[x]<deep[y]) swap(x,y); for(int i=log2(n);i>=0;--i) if(deep[fa[x][i]]>=deep[y]) x=fa[x][i]; if(x==y) return x; for(int i=log2(n);i>=0;--i) { if(fa[x][i]!=fa[y][i]) { x=fa[x][i]; y=fa[y][i]; } } return fa[x][0]; } int ask(int x,int y,int f) { int ans=0,mi=inf,ma=-inf; int t=deep[x]-deep[f]; if(t>0) { for(int i=log2(n);i>=0;--i) { if(deep[fa[x][i]]>=deep[f]) { ans=max(ans,max(ans1[x][i],maxx[x][i]-mi)); mi=min(mi,minn[x][i]);//mi的改变一定要放在ans后面,否则mi会被覆盖 x=fa[x][i]; } } } t=deep[y]-deep[f]; if(t>0) { for(int i=log2(n);i>=0;--i) { if(deep[fa[y][i]]>=deep[f]) { ans=max(ans,max(ans2[y][i],ma-minn[y][i])); ma=max(ma,maxx[y][i]); y=fa[y][i]; } } } return ans=max(ans,ma-mi); } int main() { memset(fist,-1,sizeof(fist)); scanf("%d",&n); for(int i=1;i<=n;++i) scanf("%d",&v[i]); for(int i=1;i<n;++i) { int x,y; scanf("%d%d",&x,&y); build(x,y); build(y,x); } dfs(0,1); done(); scanf("%d",&m); for(int i=1;i<=m;++i) { int x,y; scanf("%d%d",&x,&y); int f=lca(x,y); printf("%d\n",ask(x,y,f)); } return 0; }
相关文章推荐
- Codevs 3305 水果姐逛水果街Ⅱ 倍增LCA
- <线段树版>codevs 3304 水果姐逛水果街Ⅰ
- 【codevs3305】水果姐逛水果街Ⅱ LCA
- 【codevs3305】水果姐逛水果街2【树上倍增+dp】
- 【codevs3305】水果姐逛水果街Ⅱ——杨子曰题目
- CodeVs——T 3305 水果姐逛水果街Ⅱ
- <DP版>codevs 3304 水果姐逛水果街Ⅰ
- codevs 3305 水果姐逛水果街Ⅱ
- codevs3305 水果姐逛水果街Ⅱ
- codevs 3304 水果姐逛水果街Ⅰ 题解
- [Codevs] 3304 水果姐逛水果街
- 【codevs3306】水果姐逛水果街Ⅲ 树链剖分
- 【codevs3304】水果姐逛水果街
- <二分答案+spfa验证>codevs 1183 泥泞的道路
- <单调栈/悬线法>codevs 2491 玉蟾宫 1159 最大全0子矩阵
- NOIP 2013 CODE[VS] 3287 货车运输 倍增LCA + 最大生成树
- codevs3304 水果姐逛水果街
- <DP>codevs 2189 数字三角形w
- CODE[VS] 3304 水果姐逛水果街I(线段树求区间最大最小值)
- Codevs 2370 小机房的树 LCA 树上倍增