Codeforces379 F. New Year Tree
出处: 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的更多相关文章
- 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 ...
- Codeforces 379 F. New Year Tree
\(>Codeforces \space 379 F. New Year Tree<\) 题目大意 : 有一棵有 \(4\) 个节点个树,有连边 \((1,2) (1,3) (1,4)\) ...
- 2014 Super Training #9 F A Simple Tree Problem --DFS+线段树
原题: ZOJ 3686 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3686 这题本来是一个比较水的线段树,结果一个ma ...
- 【2013 ICPC亚洲区域赛成都站 F】Fibonacci Tree(最小生成树+思维)
Problem Description Coach Pang is interested in Fibonacci numbers while Uncle Yang wants him to do s ...
- 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 ...
- Problem F. Grab The Tree HDU - 6324
题意:给出一棵n个节点的树,每个节点有一个权值,Q和T玩游戏,Q先选一些不相邻的节点,T选剩下的节点,每个人的分数是所选节点的权值的异或和,权值大的胜出,问胜出的是谁. 题解: 话说,这题后面的边跟解 ...
- AtCoder Grand Contest 023 F - 01 on Tree
Description 题面 Solution HNOI-day2-t2 复制上去,删点东西,即可 \(AC\) #include<bits/stdc++.h> using namespa ...
- 泛函编程(8)-数据结构-Tree
上节介绍了泛函数据结构List及相关的泛函编程函数设计使用,还附带了少许多态类型(Polymorphic Type)及变形(Type Variance)的介绍.有关Polymorphism的详细介绍会 ...
- codeforces 675D D. Tree Construction(线段树+BTS)
题目链接: D. Tree Construction D. Tree Construction time limit per test 2 seconds memory limit per test ...
随机推荐
- Vs2017_创建项目引用Core2.2报错找不到
错误: 解决方案: 这个勾一定要画上
- Linux命令(一)
需要用Xshell连接Linux时: 先在终端输入命令:service sshd start(开启ssh服务) 1.netstat -tnl:查看端口状态的命令(如 查看22端口) 2.servi ...
- [loadrunner]通过检查点判定事务是否成功
//检查点设置语句 //tmp在此时为临时参数 web_reg_find("SaveCount=tmp", "Text=xxx", LAST); ...
- Python做windows服务
Python做windows服务(多进程服务),并结束多进程 Python中_,__,__xx__的区别 在注册MyWinService服务时,再使用 "sc delete 服务器名称&qu ...
- Elasticsearch 关键字:索引,类型,字段,索引状态,mapping,文档
1. 索引(_index)索引:说的就是数据库的名字.我这个说法是对应到咱经常使用的数据库. 结合es的插件 head 来看. 可以看到,我这个地方,就有这么几个索引,索引就是数据库,后面是这个数据库 ...
- javac与java版本不一致
项目测试时遇到该问题,因为loadRunner不支持jdk1.7,但运行java脚本时提示jdk版本是1.7,实际的JAVA_HOME设置为1.6. 运行javac -version与java -ve ...
- ES5与ES6的小差异
ES5与ES6的小差异 变量的定义 ES6与ES5的区别 ES5: <script> console.log(username); var username; var username = ...
- Linux之hosts文件
一.序言: 今天同事部署环境遇到问题, 原因1:修改了主机名,在/etc/hosts文件中加了3台集群的ip和主机名,但是将默认的前两行也改了,没注意看改了哪里, 现象: 1.zookeeper单台可 ...
- 【kindle笔记】之 《鬼吹灯》-9-20
[kindle笔记]读书记录-总 9-20 日常吐槽 连着几天,基本是一口气读完了鬼吹灯. 想来,也算是阴差阳错了.本来是想看盗墓的,读了几页开头,心想坏了,拷贝错了,这是鬼吹灯-- 讲真的,每每读小 ...
- Linux查看硬件等基本参数
http://www.cnblogs.com/xd502djj/archive/2011/02/28/1967350.html