Kth Ancestor 第k个祖先问题
这道题目出自hackerrank的8月月赛的第三题。
题目大意:
先给出一棵树
之后有三种操作分别为:加边,查询,和删除一个节点
查询的时候要给出任意节点x的第k个祖先
每组数据有t个case
每个case边(P)的数量小于等于10^5
每个case的操作的数量(Q)小于等于10^5
题目分析:
一开始拿到这个题目的时候被搞得一头雾水,如果采用普通的暴力的办法,每一个查询需要O(P),总体的复杂度就变成了O(Q*P),铁定TLE…
思考了三天没有什么想法然后搜了一下,发现了这个:
研读了一番之后发现了使用一个神奇的数据结构,使得每一次的查询可以降为long(P)的复杂度,这样问题就迎刃而解了。
这个奇特的数据结构,我这样描述:
对树进行DFS,记录下每一条路径e[i]。
之后开一个node[i]标记每个节点所在的边号(index),以及在该边的深度(depth)还有该点的“父节点”(father 该点所在边的起点e[node[i].index][0]的父节点)。
那么查询的时候Q(x,k)就等于:
k <= node[x].depth 时 return e[node[x].index][node[x].depth-k]
k > node[x].depth 时 return Q(node[x].father,k-1)
之后就是一系列的边界描述,不再赘述了。
第一次写出来的这个代码十分之丑陋,大家见笑了
python3写的

Level ancestorclass node:
def __init__(self,depth = 0,father = -1,index = -1,mark = -2):
self.depth = depth
self.father = father
self.index = index
self.mark = mark
path = []
nodes = [] MAXN = 100000+5 def NEW(x,y):
path.append([y,x])
l = len(path)-1
nodes[y] = node(0,-1,l,-1)
nodes[x] = node(0,y,l,1) def CON(x,y):
if ( nodes[y].mark == 1 ):
nodes[x] = node(nodes[y].depth+1,nodes[y].father,nodes[y].index,1)
nodes[y].mark = 0
path[nodes[y].index].append(x)
elif(( nodes[y].mark == -1 ) & ( len(path[nodes[y].index]) == 1 ) ):
nodes[x] = node(nodes[y].depth+1,nodes[y].father,nodes[y].index,1)
path[nodes[y].index].append(x)
else:
ADD(x)
l = len(path)-1
nodes[x] = node(0,y,l,1) def ADD(x):
path.append([x]) def update(x,y):
if ( ( nodes[x].mark == -2 ) & ( nodes[y].mark == -2 ) ):
NEW(x,y)
elif ( ( nodes[x].mark == -2 ) & ( nodes[y].mark != -2 ) ):
CON(x,y)
elif ( ( nodes[x].mark != -2 ) & ( nodes[y].mark != -2 ) ):
nodes[x].father = y
elif ( ( nodes[x].mark != -2 ) & ( nodes[y].mark == -2 ) ):
ADD(y)
nodes[y] = node(0,-1,len(path)-1,1)
nodes[x].father = y def DEL(x):
path[nodes[x].index].remove(x)
nodes[x] = node() def LOA(x,k):
if ( x == 0 ):
return 0;
if ( nodes[x].mark == -2 ):
return 0
if (nodes[x].depth >= k):
lt = nodes[x].depth - k
if ( path[nodes[x].index][0] == 0 ):
lt = lt+1
return path[nodes[x].index][lt]
if ( nodes[x].depth < k ):
if ( ( nodes[x].father == -1 ) or ( nodes[x].father == 0 ) ):
return 0
t = LOA(nodes[x].father,k-nodes[x].depth-1)
return t def INIT():
global path
global nodes
path = []
nodes = [node() for i in range(0,MAXN)] def build():
n = int(input())
for i in range(0,n):
x,y = input().split(' ')
x = int(x)
y = int(y)
update(x,y)
#print(path) def Q():
n = int(input())
for i in range(0,n):
lt = input().split(' ')
if ( lt[0] == '0' ):
update(int(lt[2]),int(lt[1]))
#print(path)
if ( lt[0] == '1' ):
DEL(int(lt[1]))
if ( lt[0] == '2' ):
print(LOA(int(lt[1]),int(lt[2]))) t = input()
t = int(t)
for i in range(0,t):
INIT()
build()
Q()
以后争取做到学会了就记录下来,这个代码贴给后人鄙视吧
Kth Ancestor 第k个祖先问题的更多相关文章
- Vijos lxhgww的奇思妙想--求K级祖先
给出一棵树求K级祖先.O(N*logN+Q) 更详细的讲解见:https://www.cnblogs.com/cjyyb/p/9479258.html /* 要求k级祖先,我们可以把k拆成" ...
- HDU 4006The kth great number(K大数 +小顶堆)
The kth great number Time Limit:1000MS Memory Limit:65768KB 64bit IO Format:%I64d & %I64 ...
- K-th Number(第k大数)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 45710 Accepted: 15199 Ca ...
- Vijos.lxhgww的奇思妙想(k级祖先 长链剖分)
题目链接 https://blog.bill.moe/long-chain-subdivision-notes/ http://www.cnblogs.com/zzqsblog/p/6700133.h ...
- 树链剖分 (求LCA,第K祖先,轻重链剖分、长链剖分)
2020/4/30 15:55 树链剖分是一种十分实用的树的方法,用来处理LCA等祖先问题,以及对一棵树上的节点进行批量修改.权值和查询等有奇效. So, what is 树链剖分? 可以简单 ...
- Find the largest K numbers from array (找出数组中最大的K个值)
Recently i was doing some study on algorithms. A classic problem is to find the K largest(smallest) ...
- 【POJ2985】【Treap + 并查集】The k-th Largest Group
Description Newman likes playing with cats. He possesses lots of cats in his home. Because the numbe ...
- Kth Smallest Element in a BST 解答
Question Given a binary search tree, write a function kthSmallest to find the kth smallest element i ...
- 4923: [Lydsy1706月赛]K小值查询 平衡树 非旋转Treap
国际惯例的题面:这种维护排序序列,严格大于的进行操作的题都很套路......我们按照[0,k],(k,2k],(2k,inf)分类讨论一下就好.显然第一个区间的不会变化,第二个区间的会被平移进第一个区 ...
随机推荐
- python 访问php程序,实现定时
#!/usr/bin/python #test2.py import sys import urllib2 j = True jj = 1##########用于统计,所以分页, url = 'htt ...
- SQL Trigger(触发器)
1.触发器对表进行插入.更新.删除的时候会自动执行的特殊存储过程. 2.触发器一般用在check约束更加复杂的约束上面. 3.触发器和普通的存储过程的区别是:触发器是当对某一个表进行操作. 4.upd ...
- jquery ajax post, get, javascript ajax post, get 处理
ajax 创建 XMLHttp 对象IE7 以上的版本都支持 XMLHttpRequestIE7 以下的用 ActiveXObject async:true, // 当false 时,当执行完这个才 ...
- python 函数1
一.背景 在学习函数之前,一直遵循:面向过程编程,即:根据业务逻辑从上到下实现功能,其往往用一长段代码来实现指定功能,开发过程中最常见的操作就是粘贴复制,也就是将之前实现的代码块复制到现需功能处,如下 ...
- Html DOM 常用属性和方法
Node对象的节点类型***************************************************接口 nodeType常量 nodeType值 备注Element Node ...
- websql
http://blog.darkcrimson.com/2010/05/local-databases/ http://www.oschina.net/question/12_26204 webkit ...
- Stanford Parser学习入门(3)-标记
以下是Stanford parser中的标记中文释义供参考. probabilistic context-free grammar(PCFG) ROOT:要处理文本的语句 IP:简单从句 NP ...
- Linux用户环境变量
Linux用户环境变量 环境变量就是系统或软件设置的一些参数,用户环境变量就是用户登录系统后,都有自已专用的运行环境.在Windows系统中用户环境变量保存在用户家目录,Linux也是同样的.本文主要 ...
- 【HDU 4276】The Ghost Blows Light(树形DP,依赖背包)
The Ghost Blows Light Problem Description My name is Hu Bayi, robing an ancient tomb in Tibet. The t ...
- 我新买的红米手机,新浪和360浏览器都能进,也能看电视,就是不能上手机QQ和微信
1.请您在桌面下.点击手菜单键-全局搜索,输入网络助手,点击流量排行,点击批量联网控制,查看该软件下(不能上网的应用)wifi和流量2G/3G下方的选项是否都勾选的.如果没有勾选,请您勾选. 2:仍然 ...