zoukankan      html  css  js  c++  java
  • 【CF379F】New Year Tree

    题目

    题目链接:https://codeforces.com/problemset/problem/379/F
    有一颗 \(4\) 个节点的树,\(2,3,4\) 号节点的父亲节点都是 \(1\)\(m\) 次操作。操作有 \(1\) 种:

    • u:设现在这颗树有 \(n\) 个节点,则您要新建两个节点 \(n+1,n+2\) 并让它们变为 \(u\) 的儿子节点(连一条 \(u\)\(n+1\) 的边和 \(u\)\(n+2\) 的边)。保证 \(u\) 是叶子节点。进行完操作后,您要输出此时树的直径。

    \(1\le m\le 5\times 10^5\)

    思路

    首先每次操作最多只会让直径增加 \(1\)。那么如果原来直径两端是 \(x,y\),这次加入点后直径增加了,那么 \(x,n+1\)\(y,n+1\) 中至少有一个会成为新的直径两端。
    所以只需要倍增求一下 LCA 就可以了。
    时间复杂度 \(O(m\log m)\)

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=1000010,LG=20;
    int m,x,y,f[N][LG+1],dep[N];
    
    int lca(int x,int y)
    {
    	if (dep[x]<dep[y]) swap(x,y);
    	for (int i=LG;i>=0;i--)
    		if (dep[f[x][i]]>=dep[y]) x=f[x][i];
    	if (x==y) return x;
    	for (int i=LG;i>=0;i--)
    		if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    	return f[x][0];
    }
    
    int dis(int x,int y)
    {
    	int p=lca(x,y);
    	return dep[x]+dep[y]-2*dep[p];
    }
    
    int main()
    {
    	scanf("%d",&m);
    	f[2][0]=f[3][0]=f[4][0]=1;
    	dep[2]=dep[3]=dep[4]=2; dep[1]=1;
    	x=2; y=3;
    	for (int i=1,n=5,u;i<=m;i++,n+=2)
    	{
    		scanf("%d",&u);
    		f[n][0]=f[n+1][0]=u;
    		dep[n]=dep[n+1]=dep[u]+1;
    		for (int i=1;i<=LG;i++)
    			f[n][i]=f[n+1][i]=f[f[n][i-1]][i-1];
    		if (dis(x,y)<dis(x,n)) y=n;
    		if (dis(x,y)<dis(y,n)) x=n;
    		cout<<dis(x,y)<<"\n";
    	}
    	return 0;
    }
    
  • 相关阅读:
    Flink实战(七十三):FLINK-SQL使用基础(一)简介(一)入门
    Flink实战(七十二):监控(四)自定义metrics相关指标(二)
    k8s启动
    k8s containerd
    安装containerd
    k8s镜像
    crictl
    Kubernetes: Using containerd 1.1 without Docker
    docker images --digests
    ctr images pull docker.io/library/redis:latest
  • 原文地址:https://www.cnblogs.com/stoorz/p/15520930.html
Copyright © 2011-2022 走看看