zoukankan      html  css  js  c++  java
  • 51Nod1766 树上的最远点对 ST表 LCA 线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1766.html

    题目传送门 - 51Nod1766

    题意

      n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即你需要求出max{dis(i,j) |a<=i<=b,c<=j<=d}

    题解

      只需要得到两个结论:

      设 S(A) 为点集 A 的最远点对所包含的点的集合。

      1. $S(Acap B) subset S(A)cap S(B)$

      2. 强制点对的两端点分别在集合 A,B 时,最终的点对就从 A,B 中各选一个,取距离最大的就好了。

      于是只需要线段树维护一下区间最远点对即可。

      时间复杂度 $O(nlog n)$ 。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    int read(){
    	int x=0;
    	char ch=getchar();
    	while (!isdigit(ch))
    		ch=getchar();
    	while (isdigit(ch))
    		x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return x;
    }
    const int N=100005,INF=1.05e9;
    struct Gragh{
    	static const int M=N*2;
    	int cnt,y[M],z[M],nxt[M],fst[N];
    	void clear(){
    		cnt=1;
    		memset(fst,0,sizeof fst);
    	}
    	void add(int a,int b,int c){
    		y[++cnt]=b,z[cnt]=c,nxt[cnt]=fst[a],fst[a]=cnt;
    	}
    }g;
    #define list __zzd001
    int n;
    int fa[N][20],depth[N],ld[N],Log[N*2];
    int ST[N*2][20],list[N*2],dfn=0,in[N],out[N];
    void dfs(int x,int pre,int d,int dd){
    	depth[x]=d,fa[x][0]=pre,ld[x]=dd;
    	list[in[x]=++dfn]=x;
    	for (int i=1;i<20;i++)
    		fa[x][i]=fa[fa[x][i-1]][i-1];
    	for (int i=g.fst[x];i;i=g.nxt[i])
    		if (g.y[i]!=pre){
    			dfs(g.y[i],x,d+1,dd+g.z[i]);
    			list[++dfn]=x;
    		}
    	out[x]=dfn;
    }
    int spmax(int a,int b){
    	return depth[a]<depth[b]?a:b;
    }
    void prework(){
    	for (int i=1;i<=dfn;i++){
    		ST[i][0]=list[i];
    		for (int j=1;j<20;j++){
    			ST[i][j]=ST[i][j-1];
    			if (i-(1<<(j-1))>0)
    				ST[i][j]=spmax(ST[i][j-1],ST[i-(1<<(j-1))][j-1]);
    		}
    	}
    }
    int query(int L,int R){
    	int d=Log[R-L+1];
    	return spmax(ST[L+(1<<d)-1][d],ST[R][d]);
    }
    int LCA(int x,int y){
    	return query(min(in[x],in[y]),max(in[x],in[y]));
    }
    #define fi first
    #define se second
    #define pii pair <int,int> 
    pii t[N<<2];
    int dis(int x,int y){
    	if (!~x&&!~y)
    		return -2*INF;
    	if (!~x||!~y)
    		return -INF;
    	return ld[x]+ld[y]-2*ld[LCA(x,y)];
    }
    pii Merge(pii a,pii b){
    	pii res=dis(a.fi,a.se)>dis(b.fi,b.se)?a:b;
    	if (dis(a.fi,b.fi)>dis(res.fi,res.se))res=make_pair(a.fi,b.fi);
    	if (dis(a.fi,b.se)>dis(res.fi,res.se))res=make_pair(a.fi,b.se);
    	if (dis(a.se,b.fi)>dis(res.fi,res.se))res=make_pair(a.se,b.fi);
    	if (dis(a.se,b.se)>dis(res.fi,res.se))res=make_pair(a.se,b.se);
    	return res;
    }
    void build(int rt,int L,int R){
    	if (L==R){
    		t[rt]=make_pair(L,-1);
    		return;
    	}
    	int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
    	build(ls,L,mid);
    	build(rs,mid+1,R);
    	t[rt]=Merge(t[ls],t[rs]);
    }
    pii query(int rt,int L,int R,int xL,int xR){
    	if (R<xL||L>xR)
    		return make_pair(-1,-1);
    	if (xL<=L&&R<=xR)
    		return t[rt];
    	int mid=(L+R)>>1,ls=rt<<1,rs=ls|1;
    	return Merge(query(ls,L,mid,xL,xR),query(rs,mid+1,R,xL,xR));
    }
    int main(){
    	n=read();
    	g.clear();
    	for (int i=1;i<n;i++){
    		int a=read(),b=read(),c=read();
    		g.add(a,b,c);
    		g.add(b,a,c);
    	}
    	dfs(1,0,0,0);
    	Log[1]=0;
    	for (int i=2;i<=dfn;i++)
    		Log[i]=Log[i>>1]+1;
    	prework();
    	build(1,1,n);
    	int m=read();
    	while (m--){
    		int a=read(),b=read(),c=read(),d=read();
    		pii x=query(1,1,n,a,b);
    		pii y=query(1,1,n,c,d);
    		pii res=make_pair(-1,-1);
    		if (dis(x.fi,y.fi)>dis(res.fi,res.se))res=make_pair(x.fi,y.fi);
    		if (dis(x.fi,y.se)>dis(res.fi,res.se))res=make_pair(x.fi,y.se);
    		if (dis(x.se,y.fi)>dis(res.fi,res.se))res=make_pair(x.se,y.fi);
    		if (dis(x.se,y.se)>dis(res.fi,res.se))res=make_pair(x.se,y.se);
    		printf("%d
    ",dis(res.fi,res.se));
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    .net下将富文本编辑器文本原样读入word文档
    最大流算法完整代码
    如何用程序删除win 7下SYSTEM权限的目录
    01背包问题的动态规划算法
    使用gem安装jekyll错误记录
    dev机上数据库中批量生成table
    git pull错误记录及解决
    git clone操作到开发机的错误记录
    nginx错误记录
    链表链式结构的写法
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/51Nod1766.html
Copyright © 2011-2022 走看看