[51NOD 1766]树上的最远点对
来源:互联网 发布:sem优化方案 编辑:程序博客网 时间:2024/06/16 10:19
题目大意
题目分析
可以发现最长路径具有直径的合并性质,即两个区间选点的最长路径端点一定是原本两个区间最长路径
所以我们可以直接用线段树储存区间的最长路径端点,然后合并答案即可。
注意
时间复杂度
代码实现
注:在51NOD上莫名RE了,仅作参考吧。
#include <iostream>#include <cstdio>#include <cctype>#include <cmath>using namespace std;typedef pair<int,int> P;#define mkp(a,b) make_pair(a,b)#define ft first#define sd secondint read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar(); while (isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return x*f;}const int N=100500;const int M=N<<1;const int EL=N<<1;const int LGEL=18;int last[N],deep[N],fa[N],len[N],pos[N],high[N];int n,q,tot,ord,lgel;int tov[M],next[M];int rmq[EL][LGEL];int euler[EL];int getrmq(int l,int r){ int lgr=trunc(log(r-l+1)/log(2)); if (high[rmq[l][lgr]]<high[rmq[r-(1<<lgr)+1][lgr]]) return rmq[l][lgr]; else return rmq[r-(1<<lgr)+1][lgr];}int lca(int x,int y){ x=pos[x],y=pos[y]; if (x>y) swap(x,y); return getrmq(x,y);}int dis(int x,int y){return deep[x]+deep[y]-(deep[lca(x,y)]<<1);}P merge(P x,P y){ int p1=x.ft,p2=x.sd,p3=y.ft,p4=y.sd,v1=p1,v2=p2,d0=dis(v1,v2),d; if ((d=dis(p3,p4))>d0) v1=p3,v2=p4,d0=d; if ((d=dis(p1,p3))>d0) v1=p1,v2=p3,d0=d; if ((d=dis(p1,p4))>d0) v1=p1,v2=p4,d0=d; if ((d=dis(p2,p3))>d0) v1=p2,v2=p3,d0=d; if ((d=dis(p2,p4))>d0) v1=p2,v2=p4,d0=d; return mkp(v1,v2);}P merge0(P x,P y){ int p1=x.ft,p2=x.sd,p3=y.ft,p4=y.sd,v1=p1,v2=p3,d0=dis(v1,v2),d; if ((d=dis(p1,p4))>d0) v1=p1,v2=p4,d0=d; if ((d=dis(p2,p3))>d0) v1=p2,v2=p3,d0=d; if ((d=dis(p2,p4))>d0) v1=p2,v2=p4,d0=d; return mkp(v1,v2);}struct segment_tree{ P v[N<<2]; void build(int x,int l,int r) { if (l==r) { v[x]=mkp(l,r); return; } int mid=l+r>>1; build(x<<1,l,mid),build(x<<1|1,mid+1,r); v[x]=merge(v[x<<1],v[x<<1|1]); } P query(int x,int st,int en,int l,int r) { if (st==l&&en==r) return v[x]; int mid=l+r>>1; if (en<=mid) return query(x<<1,st,en,l,mid); else if (mid+1<=st) return query(x<<1|1,st,en,mid+1,r); else merge(query(x<<1,st,mid,l,mid),query(x<<1|1,mid+1,en,mid+1,r)); }}t;void dfs(int x){ pos[euler[++ord]=x]=ord; for (int i=last[x],y;i;i=next[i]) if ((y=tov[i])!=fa[x]) { fa[y]=x,deep[y]=deep[x]+len[i],high[y]=high[x]+1,dfs(y); euler[++ord]=x; }}void insert(int x,int y,int z){ tov[++tot]=y,next[tot]=last[x],len[tot]=z,last[x]=tot;}void pre(){ for (int i=1;i<=ord;i++) rmq[i][0]=euler[i]; lgel=trunc(log(ord)/log(2)); for (int j=1;j<=lgel;j++) for (int i=1;i+(1<<j)-1<=ord;i++) if (high[rmq[i][j-1]]<high[rmq[i+(1<<j-1)][j-1]]) rmq[i][j]=rmq[i][j-1]; else rmq[i][j]=rmq[i+(1<<j-1)][j-1];}int main(){ freopen("pair.in","r",stdin),freopen("pair.out","w",stdout); n=read(); for (int i=1,x,y,z;i<n;i++) { x=read(),y=read(),z=read(); insert(x,y,z),insert(y,x,z); } dfs(1),pre(); t.build(1,1,n); q=read(); for (int i=1,a,b,c,d;i<=q;i++) { a=read(),b=read(),c=read(),d=read(); P g1=t.query(1,a,b,1,n),g2=t.query(1,c,d,1,n); g1=merge0(g1,g2); printf("%d\n",dis(g1.ft,g1.sd)); } fclose(stdin),fclose(stdout); return 0;}
0 0
- [51nod 1766]树上的最远点对
- [51NOD 1766]树上的最远点对
- 51nod 1766 树上的最远点对
- 51Nod-1766-树上的最远点对
- 51NOD1766 树上的最远点对
- [51nod1766]树上的最远点对
- 树上最远点对的线性时间算法
- hdu 2196 computer 求树上的任意最远点对 O(n)
- 寻找最远点对
- 寻找最远点对
- 寻找最远点对
- 寻找最远点对
- 寻找最远点对
- 寻找最远点对
- POJ2187-最远点对
- 求最远点对
- 平面最远点对
- 最近&最远点对
- 一招制敌 - 玩转 AngularJS 指令的 Scope (作用域)
- 【HTML】introduction to html
- iOS中URL Scheme是干嘛的
- linux内核编码风格
- mysql字段类型为int默认null,插入却显示0的解决办法,参考php代码
- [51NOD 1766]树上的最远点对
- 解读DSI405中的enqueue之:客户端和管理端队列
- Oracle EXP-00091解决方法
- springmvc集成ajax问题
- 9-5getAttribute()方法、setAttribute()方法
- ListView item错位 由于Item复用时高度不一致导致ListView 显示错误
- ubuntu 软链接 安装androidstudio时 JDK版本控制
- Glide图片加载与ImageLoade其他图片加载的区别
- C语言之学生管理系统代码(完整)