Codeforces题号:#379F

出处: Codeforces

主要算法:LCA+树的直径

难度:4.4

思路分析:

  给出q个操作,每次在一个节点上接上两个叶子。每一次询问树的直径。

  暴力做法:每一次操作暴力BFS两遍……然而……复杂度时\(O(Q * 2n\),爆到不知哪里去了。

  其实我们会发现,除非新加进来的两个点能够对直径产生影响,直径根本不会变。所以我们只需要考虑新加进来的点对原图的影响。

  那么如何操作呢?先假设没经过任何操作之前,直径的端点时2和3(事实上2,3,4中任意两个都可以),设直径的端点1为A,端点2为B。每加进来两个点x,y时,若dist(x,A)或dist(x,B)大于原先的直径,则用它们更新,并且将直径的另一个端点设置为x或y。

  下面来证明这样的做法的正确性:

  由于在讲树的直径的时候我们提到过,从任意一个点出发进行BFS,所能到达的最远点一定是树的一个直径之一。

  先假设新加进来的两个点x,y不存在,那么原先的树的直径就是A->B,并且一定是最长的了。设x,y的父亲节点为v。那么从v所能到达的最远的点一定是A或B。并且x或y到v的距离只有1,也只能是1。所以从x或y出发遍历所能够到达的最远的点一定也是A或B。而由于之前的直径是最长的,所以我当前的直径要比上一轮更长,只能是加了一,而这个1就是从x或y到v的距离的距离中产生的。

  所以我们选择x来更新(因为x和y其实是一样的,你不可能有一条直径是从x到y的,因为这样只能是2,而刚开始就已经是2了)。分别求出x到A与B的距离,如果x到A更新成功,则B=x;如果x到B更新成功,则A=x;事实上,它们只有一个能更新成功。

  于是现在问题就转化为了求两点之间距离了,LCA随便搞一搞就好了。这题还不用Dfs预处理,真是太可爱了……

代码注意点:

  由于有q次操作,每次操作增加两个点,所以点的数目是\(2q+4\),而不是\(q+4\)

Code

/** This Program is written by QiXingZhi **/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#define r read()
#define Max(a,b) (((a)>(b)) ? (a) : (b))
#define Min(a,b) (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
const int N = ;
const int INF = ;
inline int read(){
int x = ; int w = ; register int c = getchar();
while(c ^ '-' && (c < '' || c > '')) c = getchar();
if(c == '-') w = -, c = getchar();
while(c >= '' && c <= '') x = (x << ) +(x << ) + c - '', c = getchar();
return x * w;
}
vector <int> G[N];
int dep[N],f[N][];
int Q,v,cur_node,A,B,cur1,cur2,ans,Tmp_Dist;
inline void AddEdge(int u, int v){
G[u].push_back(v);
G[v].push_back(u);
}
inline void Init(){
AddEdge(,), AddEdge(,), AddEdge(,);
cur_node = ;
A = , B = ;
ans = ;
f[][] = f[][] = f[][] = ;
dep[] = ;
dep[] = dep[] = dep[] = ;
}
inline void Update(int u, int v){
f[v][] = u;
dep[v] = dep[u] + ;
for(int i = ; (<<i) <= dep[v]; ++i){
f[v][i] = f[f[v][i-]][i-];
}
}
inline int LCA(int _a, int _b){
if(dep[_a] < dep[_b]){
swap(_a, _b);
}
int a = _a, b = _b;
for(int i = ; i >= ; --i){
if(dep[a] - (<<i) < dep[b]) continue;
a = f[a][i];
}
if(a == b) return a;
for(int i = ; i >= ; --i){
if(f[a][i] == f[b][i]) continue;
a = f[a][i];
b = f[b][i];
}
return f[a][];
}
inline int GetDist(int _a, int _b){
int __lca = LCA(_a, _b);
return dep[_a]-dep[__lca]+dep[_b]-dep[__lca];
}
int main(){
Init();
Q = r;
while(Q--){
v = r;
AddEdge(v,++cur_node);
Update(v,cur_node);
AddEdge(v,++cur_node);
Update(v,cur_node);
cur1 = cur_node;
Tmp_Dist = GetDist(cur1,A);
if(Tmp_Dist > ans){
ans = Tmp_Dist;
B = cur1;
}
Tmp_Dist = GetDist(cur1,B);
if(Tmp_Dist > ans){
ans = Tmp_Dist;
A = cur1;
}
printf("%d\n",ans);
}
/*
for(int i = 1; i <= cur_node; ++i){
for(int j = 0; j <= 3; ++j){
printf("f[%d][%d] = %d\n",i,j,f[i][j]);
}
}
for(int i = 1; i <= cur_node; ++i){
printf("dep[%d] = %d\n",i,dep[i]);
}
*/
return ;
}

Codeforces379 F. New Year Tree的更多相关文章

  1. 2018 Multi-University Training Contest 3 Problem F. Grab The Tree 【YY+BFS】

    传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6324 Problem F. Grab The Tree Time Limit: 2000/1000 MS ...

  2. Codeforces 379 F. New Year Tree

    \(>Codeforces \space 379 F. New Year Tree<\) 题目大意 : 有一棵有 \(4\) 个节点个树,有连边 \((1,2) (1,3) (1,4)\) ...

  3. 2014 Super Training #9 F A Simple Tree Problem --DFS+线段树

    原题: ZOJ 3686 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3686 这题本来是一个比较水的线段树,结果一个ma ...

  4. 【2013 ICPC亚洲区域赛成都站 F】Fibonacci Tree(最小生成树+思维)

    Problem Description Coach Pang is interested in Fibonacci numbers while Uncle Yang wants him to do s ...

  5. 2018HDU多校训练-3-Problem F. Grab The Tree

    Little Q and Little T are playing a game on a tree. There are n vertices on the tree, labeled by 1,2 ...

  6. Problem F. Grab The Tree HDU - 6324

    题意:给出一棵n个节点的树,每个节点有一个权值,Q和T玩游戏,Q先选一些不相邻的节点,T选剩下的节点,每个人的分数是所选节点的权值的异或和,权值大的胜出,问胜出的是谁. 题解: 话说,这题后面的边跟解 ...

  7. AtCoder Grand Contest 023 F - 01 on Tree

    Description 题面 Solution HNOI-day2-t2 复制上去,删点东西,即可 \(AC\) #include<bits/stdc++.h> using namespa ...

  8. 泛函编程(8)-数据结构-Tree

    上节介绍了泛函数据结构List及相关的泛函编程函数设计使用,还附带了少许多态类型(Polymorphic Type)及变形(Type Variance)的介绍.有关Polymorphism的详细介绍会 ...

  9. codeforces 675D D. Tree Construction(线段树+BTS)

    题目链接: D. Tree Construction D. Tree Construction time limit per test 2 seconds memory limit per test ...

随机推荐

  1. netty同端口监听tcp和websocket协议

    前言: 软件通信七层结构(osi模型)中由协议套协议最终组成最高级应用层协议(http等等),下三层结构偏向与数据通信,上三层更偏向于数据处理,中间的传输层则是连接上三层与下三层之间的桥梁,每一层都做 ...

  2. 获得其他程序弹出菜单的内容(一个困扰许久的问题o(╯□╰)o)

    刚开始到现在公司的时候接到一个任务:开发一个activex控件,自动操作本地exe程序,当时遇到弹出菜单无法获取的问题,还好不影响,最近又遇到这个问题,绕不过去了,于是昨天花了一个上午百度了个遍,总算 ...

  3. Bootstrap 栅格 样式 组件 插件

    -----------------------------起先是我们造成习惯,后来是习惯造成我们. day 51 Bootstrap  官方网站:   bootcss.com/ <!DOCTYP ...

  4. Leetcode -- 394. Decode String

    Given an encoded string, return it's decoded string. The encoding rule is: k[encoded_string], where ...

  5. H5 标签选择器

    08-标签选择器 我是段落 我是段落 我是段落 我是段落 我是段落 我是标题 <!DOCTYPE html> <html lang="en"> <he ...

  6. Linux进程与线程的区别

    进程与线程的区别,早已经成为了经典问题.自线程概念诞生起,关于这个问题的讨论就没有停止过.无论是初级程序员,还是资深专家,都应该考虑过这个问题,只是层次角度不同罢了.一般程序员而言,搞清楚二者的概念, ...

  7. 史上最全 原生javascript的知识总结,适合新手及查资料用!

    适合右键另存为图片保存,再放大看!

  8. 关于PHP批量图片格式转换的问题--本文转成webp, 其他过程格式一样

    最近要把项目中的图片全部生成webp格式, 过程整理一下,    (直接存在本地,或者图片链接存在数据库都可以看看) 首先,肯定是批量处理, 一个php处理不了这么多, 会爆内存的, 个人建议用aja ...

  9. hdu1421_搬寝室

    题目:搬寝室 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1421 #include<stdio.h> #include<algor ...

  10. 使用withCount后再使用select设置查询的字段。就找不到withCount的数据了

    https://laravelacademy.org/index.php/discussion/1021 如:Article::withCount(['comments'])->select(' ...