poj 3728 The merchant
来源:互联网 发布:包就业java 培训班 编辑:程序博客网 时间:2024/05/16 02:00
题意:
求树上x->y的路径最大差值,且大的权在小的权之后。
题解:
挺好的一道经典陈题。
首先好像有种差分+树剖的做法,但太恶心。
扫一眼题解,发现要维护一大堆东西,于是YY了下,好像可以。
大概是这样的:
struct trnode{ int dis,fa[20],max[20],min[20],up[20],down[20];}tr[50010];
分别是,x的
写考虑暴力做法,枚举路径,用当前值-已有的最小值更新答案。
那么现在可以倍增求这些东西,分两段,x->lca与lca->y。 我也不知道在口胡什么,具体代码
还有种离线的做法,然而我并不会,丢链接:ozy
总结:
想做这种题最好别想太多,变一变就好。
有时就差一点灵感。
剩下99%都是码代码。
但灵感更重要。
code:
#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>using namespace std;const int inf=(1<<28);struct node{ int y,next;}a[100010];int len=0,last[50010];int n,w[50010];struct trnode{ int dis,fa[20],max[20],min[20],up[20],down[20];}tr[50010];void ins(int x,int y){ a[++len].y=y; a[len].next=last[x];last[x]=len;}void cmax(int &x,int y){x=max(x,y);}void cmin(int &x,int y){x=min(x,y);}void dfs(int x,int fa){ tr[x].dis=tr[fa].dis+1; tr[x].fa[0]=fa; if(fa!=0) cmax(tr[x].up[0],w[fa]-w[x]); if(fa!=0) cmax(tr[x].down[0],w[x]-w[fa]); tr[x].max[0]=tr[x].min[0]=w[x]; if(fa!=0) cmax(tr[x].max[0],w[fa]); if(fa!=0) cmin(tr[x].min[0],w[fa]); for(int i=1;(1<<i)<=tr[x].dis;i++) { int y=tr[x].fa[i-1]; tr[x].fa[i]=tr[y].fa[i-1]; cmax(tr[x].up[i],max(tr[x].up[i-1],tr[y].up[i-1])); cmax(tr[x].up[i],tr[y].max[i-1]-tr[x].min[i-1]); cmax(tr[x].down[i],max(tr[x].down[i-1],tr[y].down[i-1])); cmax(tr[x].down[i],tr[x].max[i-1]-tr[y].min[i-1]); tr[x].max[i]=max(tr[x].max[i-1],tr[y].max[i-1]); tr[x].min[i]=min(tr[x].min[i-1],tr[y].min[i-1]); } for(int i=last[x];i;i=a[i].next) { int y=a[i].y; if(y!=fa) dfs(y,x); }}int getlca(int x,int y){ if(tr[x].dis<tr[y].dis) swap(x,y); for(int i=18;i>=0;i--) if((1<<i)<=tr[x].dis-tr[y].dis) x=tr[x].fa[i]; if(x==y) return x; for(int i=18;i>=0;i--) if((1<<i)<=tr[x].dis&&tr[x].fa[i]!=tr[y].fa[i]) x=tr[x].fa[i],y=tr[y].fa[i]; return tr[x].fa[0];}int solve(int x,int y){ int lca=getlca(x,y); int ans=0; int mx=w[y],mn=w[x]; for(int i=18;i>=0;i--) if((1<<i)<=tr[x].dis-tr[lca].dis) { cmax(ans,tr[x].up[i]); cmax(ans,tr[x].max[i]-mn); cmin(mn,tr[x].min[i]); x=tr[x].fa[i]; } for(int i=18;i>=0;i--) if((1<<i)<=tr[y].dis-tr[lca].dis) { cmax(ans,tr[y].down[i]); cmax(ans,mx-tr[y].min[i]); cmax(mx,tr[y].max[i]); y=tr[y].fa[i]; } cmax(ans,mx-mn); return ans;}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<n;i++) { int x,y;scanf("%d %d",&x,&y); ins(x,y);ins(y,x); } tr[0].dis=-1;dfs(1,0); int q;scanf("%d",&q); while(q--) { int x,y;scanf("%d %d",&x,&y); printf("%d\n",solve(x,y)); }}
阅读全文
2 0
- POJ 3728 The merchant
- poj 3728 The merchant
- POJ 3728 The merchant
- POJ-3728-The merchant
- POJ 3728 【The merchant】
- POJ 3728 The merchant
- POJ 3728 The merchant
- poj 3728 The merchant
- POJ 3728 The merchant
- The merchant - POJ 3728 LCA
- POJ 3728:The merchant LCA
- |poj 3728|LCA|The merchant
- poj 3728 The merchant(tarjan求lca)
- POJ 3728 The merchant (Tarjan LCA)
- POJ 3728 The merchant LCA+倍增dp
- *POJ 3728 - The merchant(LCA‘ Tarjan)
- POJ - 3728 The merchant(dp+LCA)
- POJ 3728The merchant (LCA)
- 为什么java要实现接口Serializable
- 537. Complex Number Multiplication
- 训练日记 17.9.21
- 20170921表单标签
- [BZOJ]4953: [Wf2017]Posterize DP
- poj 3728 The merchant
- 使用zTree插件实现可拖拽的树
- 数据结构与算法(9)---Java语言实现:希尔排序
- 【分治计数|单调栈】51Nod 1215 数组的宽度
- 二分查找及STL
- UVa 12216 表达式树,map(不会)
- HD-27-水池数目(搜索)
- minnowboard 安装ubuntu16.04系统
- pgsql查询统计每天的数据