• JZOJ3690. 【CF418D】Big Problems for Organizers


    Description

    传送门

    • 给定一棵树,m次询问x,y,每个点的距离定义为到x和y的最小距离,求所有点的距离的最大值。
    • n,m<=100000

    Solution

    • 找到x到y路径的中点,将树分成两个部分,一边求到x的,一边求到y的。
    • 钦定dep[x]>dep[y],那么答案就分为:
    • 中点到x路径上伸出去节点距离。
    • 中点到LCA上的距离
    • LCA到y上伸出去节点距离。
    • LCA以上的距离。
    • x子树,y子树,LCA子树但不包括x,y所在儿子的子树。
    • 倍增记f[x][i]为x跳2i步到y,不包括x的子树的点到y的最大距离。
    • g[x][i]为到x的最大距离。
    • 计算一下。
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #define mcpy(a,b) memcpy(a,b,sizeof(a))
    #define maxn 100005
    #define maxm 200005
    #define maxp 18
    #define inf 1e9
    using namespace std;
    
    int n,i,j,k,x,y;
    int em,e[maxm],nx[maxm],ls[maxn];
    int dep[maxn],fa[maxn][maxp],f[maxn][maxp],g[maxn][maxp];
    int mx[maxn],mx0[maxn][2],mx1[maxn][2],mx2[maxn][2]; 
    vector<int> a;
    
    void insert(int x,int y){
    	em++; e[em]=y; nx[em]=ls[x]; ls[x]=em;
    	em++; e[em]=x; nx[em]=ls[y]; ls[y]=em;
    }
    
    void upd(int x,int y,int dep){
    	if (dep>=mx0[x][0]) {
    		mcpy(mx2[x],mx1[x]);
    		mcpy(mx1[x],mx0[x]);
    		mx0[x][0]=dep,mx0[x][1]=y;
    	} else 
    	if (dep>=mx1[x][0]) {
    		mcpy(mx2[x],mx1[x]);
    		mx1[x][0]=dep,mx1[x][1]=y;
    	} else
    	if (dep>=mx2[x][0]) {
    		mx2[x][0]=dep,mx2[x][1]=y;
    	}
    }
    
    void DFS(int x,int p){
    	dep[x]=dep[p]+1;
    	mx[x]=0;
    	for(int i=ls[x];i;i=nx[i]) if (e[i]!=p){
    		DFS(e[i],x),mx[x]=max(mx[x],mx[e[i]]+1);
    		upd(x,e[i],mx[e[i]]+1);
    	}
    	for(int i=ls[x];i;i=nx[i]) if (e[i]!=p) 
    		a.push_back(e[i]);
    	int mxnow=0;
    	for(int i=0;i<a.size();i++) {
    		f[a[i]][0]=max(f[a[i]][0],mxnow);
    		g[a[i]][0]=max(g[a[i]][0],mxnow+1);
    		mxnow=max(mxnow,mx[a[i]]+1);
    	}
    	mxnow=0;
    	for(int i=a.size()-1;i>=0;i--) {
    		f[a[i]][0]=max(f[a[i]][0],mxnow);
    		g[a[i]][0]=max(g[a[i]][0],mxnow+1);
    		mxnow=max(mxnow,mx[a[i]]+1);
    	}
    	a.clear();
    	fa[x][0]=p;
    }
    
    int pre[maxn];
    void DFS2(int x,int p){
    	pre[x]=g[x][0];
    	if (p) pre[x]=max(pre[x],pre[p]+1);
    	for(int i=1;i<maxp;i++){
    		fa[x][i]=fa[fa[x][i-1]][i-1];
    		if (fa[x][i]){
    			f[x][i]=max(f[fa[x][i-1]][i-1],f[x][i-1]+(1<<i-1));
    			g[x][i]=max(g[fa[x][i-1]][i-1]+(1<<i-1),g[x][i-1]);
    		} else break;
    	}
    	for(int i=ls[x];i;i=nx[i]) if (e[i]!=p)
    		DFS2(e[i],x);
    }
    
    int lca(int x,int y){
    	if (dep[x]<dep[y]) swap(x,y);
    	for(int i=maxp-1;i>=0;i--) if (dep[fa[x][i]]>=dep[y])
    		x=fa[x][i];
    	if (x==y) return x;
    	for(int i=maxp-1;i>=0;i--) if (fa[x][i]!=fa[y][i])
    		x=fa[x][i],y=fa[y][i];
    	return fa[x][0];
    }
    
    int jumpdown(int st,int len,int &p){
    	int mx=0,x=st;
    	for(int m=len,i=maxp-1;i>=0;i--) if (m>=(1<<i)){
    		mx=max(mx,g[x][i]+len-m);
    		x=fa[x][i];
    		m-=1<<i;
    	}
    	p=x;
    	return mx;
    }
    
    int jumpup(int st,int len){
    	int mx=-1e9;
    	for(int m=len,i=maxp-1,x=st;i>=0;i--) if (m>=(1<<i)){
    		mx=max(mx+(1<<i),f[x][i]);
    		x=fa[x][i];
    		m-=1<<i;
    	}
    	return mx;
    }
    
    int up(int x,int k){
    	for(int i=maxp-1;i>=0;i--) if (k>=(1<<i))
    		x=fa[x][i],k-=1<<i;
    	return x;
    }
    
    int fromLCA(int x,int p1,int p2){
    	int mx=pre[x];
    	if (p1!=mx0[x][1]&&p2!=mx0[x][1]) mx=max(mx,mx0[x][0]);
    	if (p1!=mx1[x][1]&&p2!=mx1[x][1]) mx=max(mx,mx1[x][0]);
    	if (p1!=mx2[x][1]&&p2!=mx2[x][1]) mx=max(mx,mx2[x][0]);
    	return mx;
    }
    
    int main(){
    	scanf("%d",&n);
    	for(i=1;i<n;i++) {
    		scanf("%d%d",&x,&y);
    		insert(x,y);
    	}
    	DFS(1,0);
    	DFS2(1,0);
    	int m,ans;
    	scanf("%d",&m);
    	for(i=1;i<=m;i++){
    		scanf("%d%d",&x,&y);
    		if (dep[y]>dep[x]) swap(x,y);
    		int z=lca(x,y);
    		int len=(dep[x]-dep[z]+dep[y]-dep[z])/2;
    		int p,xx=up(x,dep[x]-dep[z]-1),yy=up(y,dep[y]-dep[z]-1);
    		
    		if (dep[x]==dep[y]) {
    			ans=jumpdown(x,dep[x]-dep[z]-1,p);
    			ans=max(ans,mx[x]);
    			ans=max(ans,jumpdown(y,dep[y]-dep[z]-1,p));
    			ans=max(ans,mx[y]);
    			ans=max(ans,fromLCA(z,xx,yy)+dep[x]-dep[z]);
    		} else{
    			ans=jumpdown(x,len,p);
    			ans=max(ans,mx[x]);
    			if (fa[p][0]==z) 
    				k=-1; 
    			else {
    				k=jumpup(p,dep[p]-dep[z]-1);
    			}
    			k=max(k+1,fromLCA(z,xx,yy));
    			if (y!=z) {
    				ans=max(ans,jumpdown(y,dep[y]-dep[z]-1,p));
    				ans=max(ans,mx[y]);
    			}
    			ans=max(ans,k+dep[y]-dep[z]);
    		}
    		printf("%d
    ",ans);
    	}
    }
    
  • 相关阅读:
    STM32 IIC双机通信—— HAL库硬件IIC版
    利用 ST-LINK Utility软件下载程序
    STM32CubeMx的使用分享
    STM32 GPIO重映射(转)
    IIC 原理讲解
    STM32 软件模拟 IIC 代码,标准库、HAL库可用
    STM32 抢占优先级和响应优先级
    浅谈C中的malloc和free
    C语言-cout<<"123"<<"45"<<endl;
    VC6-Win7下VC++6.0打开多个工程的设置
  • 原文地址:https://www.cnblogs.com/DeepThinking/p/13090977.html
Copyright © 2020-2023  润新知