[51nod 1766]树上的最远点对
来源:互联网 发布:淘宝拍了不发货怎么办 编辑:程序博客网 时间:2024/06/07 01:04
题目大意
给定一棵树,m个询问每次询问从a~b选一个结点并从c~d选一个结点使这两个结点距离最大。
结论
根据树的直径性质我们得到一个结论:
一个集合中的直径两端点一定被分成两个非空集合后两条直径的四个端点包含。
于是线段树维护。
注意你求lca不能倍增,应该用RMQ求。
RMQ求LCA的方法:得到树的欧拉序与对应深度序,设fi[x]表示结点x最早出现在欧拉序中的位置。假若满足fi[x]<=z<=fi[y]的一个z是深度序中[fi[x],fi[y]]最小的,那么dfn[z]就是x与y的LCA。
#include<cstdio>#include<algorithm>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)using namespace std;const int maxn=100000+10;int h[maxn],go[maxn*2],dis[maxn*2],next[maxn*2],d[maxn],dep[maxn],f[maxn*2][25],dfn[maxn*2],fi[maxn];struct dong{ int x,y;} tree[maxn*5];int i,j,k,l,t,n,m,tot,ans,top;dong ans1,ans2;int lca(int x,int y){ x=fi[x];y=fi[y]; if (x>y) swap(x,y); int z=floor(log(y-x+1)/log(2)); if (dep[dfn[f[x][z]]]<dep[dfn[f[y-(1<<z)+1][z]]]) return dfn[f[x][z]];else return dfn[f[y-(1<<z)+1][z]];}int getdis(int x,int y){ return d[x]+d[y]-d[lca(x,y)]*2;}void merge(dong a,dong b,dong &c){ if (a.x==0){ c=b; return; } else if (b.x==0){ c=a; return; } int i,j,x=0,y=0,l=0,t; int e[5]; e[1]=a.x;e[2]=a.y;e[3]=b.x;e[4]=b.y; fo(i,1,3) fo(j,i+1,4){ t=getdis(e[i],e[j]); if (t>l){ l=t; x=e[i]; y=e[j]; } } c.x=x;c.y=y;}void add(int x,int y,int z){ go[++tot]=y; dis[tot]=z; next[tot]=h[x]; h[x]=tot;}void dfs(int x,int y){ dep[x]=dep[y]+1; dfn[++top]=x; fi[x]=top; int t=h[x]; while (t){ if (go[t]!=y){ d[go[t]]=d[x]+dis[t]; dfs(go[t],x); dfn[++top]=x; } t=next[t]; }}void build(int p,int l,int r){ if (l==r){ tree[p].x=tree[p].y=l; return; } int mid=(l+r)/2; build(p*2,l,mid); build(p*2+1,mid+1,r); merge(tree[p*2],tree[p*2+1],tree[p]);}void query(int p,int l,int r,int a,int b){ if (l==a&&r==b){ merge(ans1,tree[p],ans1); return; } int mid=(l+r)/2; if (b<=mid) query(p*2,l,mid,a,b); else if (a>mid) query(p*2+1,mid+1,r,a,b); else{ query(p*2,l,mid,a,mid); query(p*2+1,mid+1,r,mid+1,b); }}int read(){ int x=0,f=1; char ch=getchar(); while (ch<'0'||ch>'9'){ if (ch=='-') f=-1; ch=getchar(); } while (ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*f;}int main(){ //freopen("tree.in","r",stdin); n=read(); fo(i,1,n-1){ j=read();k=read();l=read(); add(j,k,l); add(k,j,l); } dfs(1,0); fo(i,1,top) f[i][0]=i; fo(j,1,log(top)/log(2)) fo(i,1,top-(1<<j)+1) if (dep[dfn[f[i][j-1]]]<dep[dfn[f[i+(1<<(j-1))][j-1]]]) f[i][j]=f[i][j-1];else f[i][j]=f[i+(1<<(j-1))][j-1]; build(1,1,n); m=read(); while (m--){ j=read();k=read();l=read();t=read(); ans1.x=0; query(1,1,n,j,k); ans2=ans1; ans1.x=0; query(1,1,n,l,t); ans=getdis(ans1.x,ans2.x); t=getdis(ans1.x,ans2.y); if (t>ans) ans=t; t=getdis(ans1.y,ans2.y); if (t>ans) ans=t; t=getdis(ans1.y,ans2.x); if (t>ans) ans=t; printf("%d\n",ans); }}
0 0
- [51nod 1766]树上的最远点对
- [51NOD 1766]树上的最远点对
- 51nod 1766 树上的最远点对
- 51Nod-1766-树上的最远点对
- 51NOD1766 树上的最远点对
- [51nod1766]树上的最远点对
- 树上最远点对的线性时间算法
- hdu 2196 computer 求树上的任意最远点对 O(n)
- 寻找最远点对
- 寻找最远点对
- 寻找最远点对
- 寻找最远点对
- 寻找最远点对
- 寻找最远点对
- POJ2187-最远点对
- 求最远点对
- 平面最远点对
- 最近&最远点对
- Robot FrameWork自动测试之入门范例
- 拯救2K屏手机!修改屏幕分辨率省电教程
- C/C++程序实现通过http代理访问网页内容
- Ubuntu每次打开终端出现错误提示的解决方法
- 高性能计算中心汇总(原创)
- [51nod 1766]树上的最远点对
- CSS Secret——Visual Effect
- 欢迎使用CSDN-markdown编辑器
- 全能安卓手机修改器,能使你的手机变成无数款不同的手机
- scikit learn 模块 调参 pipeline+girdsearch
- 日夜间模式
- 当前标识没有对“C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files”的写访问
- js 获取日期xxxx-xx-xx格式
- hibernate关联映射与集合映射详解