题目出处

这道题目出自hackerrank的8月月赛的第三题。

题目大意

先给出一棵树

之后有三种操作分别为:加边,查询,和删除一个节点

查询的时候要给出任意节点x的第k个祖先

每组数据有t个case

每个case边(P)的数量小于等于10^5

每个case的操作的数量(Q)小于等于10^5

题目分析

一开始拿到这个题目的时候被搞得一头雾水,如果采用普通的暴力的办法,每一个查询需要O(P),总体的复杂度就变成了O(Q*P),铁定TLE…

思考了三天没有什么想法然后搜了一下,发现了这个:

Level ancestor problem

研读了一番之后发现了使用一个神奇的数据结构,使得每一次的查询可以降为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个祖先问题的更多相关文章

  1. Vijos lxhgww的奇思妙想--求K级祖先

    给出一棵树求K级祖先.O(N*logN+Q) 更详细的讲解见:https://www.cnblogs.com/cjyyb/p/9479258.html /* 要求k级祖先,我们可以把k拆成" ...

  2. HDU 4006The kth great number(K大数 +小顶堆)

    The kth great number Time Limit:1000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64 ...

  3. K-th Number(第k大数)

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 45710   Accepted: 15199 Ca ...

  4. Vijos.lxhgww的奇思妙想(k级祖先 长链剖分)

    题目链接 https://blog.bill.moe/long-chain-subdivision-notes/ http://www.cnblogs.com/zzqsblog/p/6700133.h ...

  5. 树链剖分 (求LCA,第K祖先,轻重链剖分、长链剖分)

      2020/4/30   15:55 树链剖分是一种十分实用的树的方法,用来处理LCA等祖先问题,以及对一棵树上的节点进行批量修改.权值和查询等有奇效. So, what is 树链剖分? 可以简单 ...

  6. 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) ...

  7. 【POJ2985】【Treap + 并查集】The k-th Largest Group

    Description Newman likes playing with cats. He possesses lots of cats in his home. Because the numbe ...

  8. Kth Smallest Element in a BST 解答

    Question Given a binary search tree, write a function kthSmallest to find the kth smallest element i ...

  9. 4923: [Lydsy1706月赛]K小值查询 平衡树 非旋转Treap

    国际惯例的题面:这种维护排序序列,严格大于的进行操作的题都很套路......我们按照[0,k],(k,2k],(2k,inf)分类讨论一下就好.显然第一个区间的不会变化,第二个区间的会被平移进第一个区 ...

随机推荐

  1. 每天一条linux命令——shutdown

    shutdown命令用来系统关机命令.shutdown指令可以关闭所有程序,并依用户的需要,进行重新开机或关机的动作. 语法: shutdown(选项)(参数) 选项: -c:当执行“shutdown ...

  2. 深入了解absolute

    1.absolute与float的相同的特性表现  a.包裹性  b.破坏性:父元素没有设置高或宽,父元素的高或宽取决于这个元素的内容  c.不能同时存在 2.absolute独立使用,不与relat ...

  3. tabbar - 取消系统渲染

    /**  1. 取消自动渲染 - 图片***/ viewCon1.tabBarItem.selectedImage = [[UIImage imageNamed:@"tabbar_home_ ...

  4. bzoj 2401: 陶陶的难题I 数论

    2401: 陶陶的难题I Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 89  Solved: 24[Submit][Status] Descript ...

  5. 听同事讲 Bayesian statistics: Part 2 - Bayesian inference

    听同事讲 Bayesian statistics: Part 2 - Bayesian inference 摘要:每天坐地铁上班是一件很辛苦的事,需要早起不说,如果早上开会又赶上地铁晚点,更是让人火烧 ...

  6. 得到bundle seed id

    - (NSString *)bundleSeedID { NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys: (__br ...

  7. check、continue、exit的区别

    DATA:BEGIN OF lt_table OCCURS 0,      i_row   TYPE i,      i_col   TYPE i,     END OF lt_table. lt_t ...

  8. csu 10月 月赛 I 题 The Contest

    Description 殷犇有很多队员.他们都认为自己是最强的,于是,一场比赛开始了~ 于是安叔主办了一场比赛,比赛有n个题目,每个题目都有一个价值Pi和相对能力消耗Wi,但是有些题目因为太坑不能同时 ...

  9. hdu 3394 Railway

    这是一道用tarjin求双连通分量的题: 其中,不需要修的道路就是桥的数目: 在图的每个极大环中,如果点的数目小于边的数目,显然这个环中含有子环,并且这个环的边数就是这个环中有冲突的边的数目: 如果点 ...

  10. 李洪强iOS开发Swift篇—03_字符串和数据类型

    李洪强iOS开发Swift篇—03_字符串和数据类型 一.字符串 字符串是String类型的数据,用双引号""包住文字内容  let website = "http:// ...