Kth Ancestor
Difficulty: Hard

A tree of $P$ nodes is an un-directed connected graph having $P-1$ edges. Let us denote $R$ as the root node. If $A$ is a node such that it is at a distance of $L$ from $R$, and $B$ is a node such that it is at at distance of $L+1$ from 
$R$ and $A$ is connected to $B$, then we call $A$ as the parent of $B$. 

Similarly, if $A$ is at a distance of $L$ from $R$ and $B$ is at a distance of $L+K$ from $R$ and there is a path of length $K$ from $A$ to $B$, then we call $A$ as the $K$<sup>th</sup> parent of $B$. 

Susan likes to play with graphs and Tree data structure is one of her favorites. She has designed a problem and wants to know if anyone can solve it. Sometimes she adds or removes a leaf node. Your task is to figure out the $K$<sup>th</sup> parent of a node at any instant.


Input Format:
The first line contain an integer $T$ denoting the number of test cases. $T$ test cases follow. First line of each test case contains an integer $P$, the number of nodes in the tree.
$P$ lines follows each containing two integers $X$ and $Y$ separated by a single space denoting $Y$ as the parent of $X$. If $Y$ is $0$, then X is the root node of the tree.  ($0$ is for namesake and is not in the tree).  
The next line contains an integer $Q$, the number of queries.  
$Q$ lines follow each containing a query.  


+ $0$ $Y$ $X$  : $X$ is added as a new leaf node whose parent is $Y$ . $X$ is not in the tree while $Y$ is in. 
+ $1$ $X$     : This tells that leaf node $X$ is removed from the tree. $X$ is a leaf in the tree. 
+ $2$ $X$ $K$   : In this query output the $K$<sup>th</sup> parent of $X$ . $X$ is a node in the tree. 

**Note** 

+ Each node index is any number between 1 and 10<sup>5</sup> i.e., a tree with a single node can have its root indexed as 10<sup>5</sup>


Output Format:
For each query of type $2$, output the $K$<sup>th</sup> parent of $X$. If $K$<sup>th</sup> parent doesn't exist, output $0$ and if the node doesn't exist, output $0$.


Sample Input:
    2
    7
    2 0
    5 2
    3 5
    7 5
    9 8
    8 2
    6 8
    10
    0 5 15
    2 15 2
    1 3
    0 15 20
    0 20 13
    2 13 4
    2 13 3
    2 6 10
    2 11 1
    2 9 1
    1
    10000 0
    3
    0 10000 4
    1 4
    2 4 1


Sample Output:
    2
    2
    5
    0
    0
    8
    0


Python 3 starter code:

Editorial: Kth Parent : August 2020 Editorial
<style id="MathJax_SVG_styles">.MathJax_SVG_Display {text-align: center; margin: 1em 0em; position: relative; display: block!important; text-indent: 0; max-width: none; max-height: none; min-width: 0; min-height: 0; width: 100%}
.MathJax_SVG .MJX-monospace {font-family: monospace}
.MathJax_SVG .MJX-sans-serif {font-family: sans-serif}
.MathJax_SVG {display: inline; font-style: normal; font-weight: normal; line-height: normal; font-size: 100%; font-size-adjust: none; text-indent: 0; text-align: left; text-transform: none; letter-spacing: normal; word-spacing: normal; word-wrap: normal; white-space: nowrap; float: none; direction: ltr; max-width: none; max-height: none; min-width: 0; min-height: 0; border: 0; padding: 0; margin: 0}
.MathJax_SVG * {transition: none; -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none}
.mjx-svg-href {fill: blue; stroke: blue}
</style><svg style="display: none;"><defs id="MathJax_SVG_glyphs"></defs></svg><p><strong>Problem Statement</strong></p>

<p>Susan needs to find the k<sup>th</sup> parent of a node in the tree.</p>

<p><strong>Difficulty level</strong> Medium</p>

<p><strong>Required Knowledge</strong> Trees, Binary Logic</p>

<p><strong>Time Complexity</strong> O(NlogN)</p>

<p><strong>Approach</strong></p>

<p>The naive approach for this problem is very obvious. Just store the parent of each node and find the k<sup>th</sup> parent by finding parent of each parent. But as the number of queries are large, this approach in the worst case (example: tree having only two leaf nodes) exceeds time limit.</p>

<p>The pick of the problem is that, instead of storing the parent of every node, we store all 2<sup>i</sup>th parent of a node i.e. 2<sup>0</sup>th , 2<sup>1</sup>st, 2<sup>2</sup>th ... parent for each node.   </p>

<p>Now for finding k<sup>th</sup> parent of a node A,   </p>

<p>Let, <br>
k = (b<sub>l-1</sub>b<sub>l-2</sub>....b<sub>0</sub>) in binary representation be a l-bit number k. </p>

<p>So k = b<sub>0</sub> + b<sub>1</sub> * 2<sup>1</sup> + ... + b<sub>l-2</sub> * 2<sup>l-2</sup> + b<sub>l-1</sub> * 2<sup>l-1</sup>  </p>

<p>Let s bits of these l bits are 1, p1,p2,...ps be indices at which bit value is 1. <br>
k = 2<sup>p1</sup> + 2<sup>p2</sup> + ... + 2<sup>ps</sup>  </p>

<p>Using above distribution of k, we can find kth node by following procedure. <br>
A1 = 2<sup>p1</sup>th parent of A <br>
A2 = 2<sup>p2</sup>th parent of A1, implies 2<sup>p1</sup>th + 2<sup>p2</sup>th parent of A <br>
A3 = 2<sup>p3</sup>th parent of A2 which will also be 2<sup>p1</sup>th + 2<sup>p2</sup>th + 2<sup>p3</sup>th parent of A.  </p>

<p>Similarly <br>
As = 2<sup>ps</sup>th parent of As-1 and also 2<sup>p1</sup>th+2<sup>p2</sup>th .... 2<sup>ps</sup>th parent of A i.e. k<sup>th</sup> parent of A.</p>

<p>So it takes only s summations for finding k<sup>th</sup> parent. Since s is the number of bits in k.
So this process takes O(s) = O(log k) time;</p>

<p>Now the problem is how to find 2<sup>i</sup> parents of each node?</p>

<p>Let parent[i][j] be 2<sup>j</sup>th parent of node i.
Initially we know parent[i][0] i.e. first parent of all the nodes.</p>

<p>For j&gt;0</p>

<pre><code>parent[i][j] =  2^jth parent of i   
             =  (2^j-1th + 2^j-1th) parent of i   
             =  2^j-1th parent of (2^j-1th parent of i)    
             =  2^j-1th parent of parent[i][j-1]   
             =  parent[parent[i][j-1][j-1]  
</code></pre>

<p>The pseudo code is as follows</p>

<pre><code>for i from 1 to n
    parent[i][0] = parent of i

for i from 1 to n
    for j from 1 to m
        parent[i][j] = parent[parent[i][j-1]][j-1]
</code></pre>

<p>In above code, m is the maximum value j can attain. In worst case, the highest value of parent a node can have is n-1.  </p>

<p>2^m&lt;=n-1
m = O(log n)</p>

<p>Hence above process takes O(n log n) time as well as O(n log n) space.</p>

<p><strong>Problem Setter's code</strong>  </p>

<pre><code>//shashwat001

#include &lt;cstdio&gt;
#include &lt;cstring&gt;
#include &lt;cstdlib&gt;
#include &lt;cmath&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;vector&gt;
#include &lt;set&gt;
#include &lt;queue&gt;
#include &lt;stack&gt;
#include &lt;map&gt;
#include &lt;utility&gt;
#include &lt;algorithm&gt;
#include &lt;cassert&gt;

using namespace std;

#define INF 2147483647
#define LINF 9223372036854775807
#define mp make_pair
#define pb push_back

typedef long long int lli;
typedef pair&lt;int,int&gt; pi;

int p[100000][40]={{0}};
int a[100005],isnode[100005];
int main ()
{

    int q,ch,x,y,t;
    scanf("%d",&amp;t);
    assert(t&gt;=1 &amp;&amp; t&lt;=3);
    while(t--)
    {
        memset(p,0,sizeof(p));
        memset(isnode,0,sizeof(isnode));
        int i,n,j;
        scanf("%d",&amp;n);
        assert(n&gt;=1 &amp;&amp; n&lt;=100000);
        for(i = 0;i &lt; n;i++)
        {
            scanf("%d %d",&amp;x,&amp;y);
            assert(x&gt;=1 &amp;&amp; x&lt;=100000);
            assert(y&gt;=0 &amp;&amp; y&lt;=100000);
            a[i] = x;
            if(y!=0)
                assert(isnode[y]==1);
            assert(isnode[x]==0);
            isnode[x] = 1;
            p[x][0] = y;
        }
        int lgn = (int)(log(n)/log(2))+1;
        for(j = 1;j&lt;=lgn;j++)
        {
            for(i = 0;i &lt; n;i++)
            {
                p[a[i]][j] = p[p[a[i]][j-1]][j-1];
            }
        }

        scanf("%d",&amp;q);
        assert(q&gt;0 &amp;&amp; q&lt;=100000);
        for(i = 0;i &lt; q;i++)
        {
            scanf("%d",&amp;ch);
            assert(ch&gt;=0 &amp;&amp; ch&lt;=2);
            if(ch == 0) //Add an edge
            {
                scanf("%d %d",&amp;x,&amp;y);

                assert(y&gt;=1 &amp;&amp; y&lt;=100000);
                assert(x&gt;=1 &amp;&amp; x&lt;=100000);

                assert(isnode[x]==1);
                assert(isnode[y]==0);
                isnode[y] = 1;
                p[y][0] = x;
                j = 0;
                while(p[y][j]!=0)
                {
                    p[y][j+1] = p[p[y][j]][j];
                    j++;
                }
                while(j&lt;=lgn)
                {
                    p[y][j] = 0;
                    j++;
                }
            }
            else if(ch == 1) //Remove an edge
            {
                scanf("%d",&amp;x);
                assert(x&gt;=1 &amp;&amp; x&lt;=100000);
                assert(isnode[x]==1);
                isnode[x] = 0;
                for(j = 0;j &lt;= lgn;j++)
                {
                    p[x][j] = 0;
                }
            }
            else
            {
                scanf("%d %d",&amp;x,&amp;y);
                assert(x&gt;=1 &amp;&amp; x&lt;=100000);
                assert(y&gt;=1 &amp;&amp; y&lt;=100000);
                j = 0;
                while(y&gt;0)
                {
                    if(y&amp;1)
                        x = p[x][j];
                    y = y&gt;&gt;1;
                    j++;
                }
                printf("%d\n",x);
            }
        }
    }
    return 0;
}
</code></pre>

Reference solution (C++):
###C++  
```cpp  
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <map>
#include <utility>
#include <algorithm>
#include <cassert>
    
using namespace std;
    
#define INF 2147483647
#define LINF 9223372036854775807
#define mp make_pair
#define pb push_back
    
typedef long long int lli;
typedef pair<int,int> pi;
    
int p[100000][40]={{0}};
int a[100005],isnode[100005];
int main ()
{
    
    int q,ch,x,y,t;
    scanf("%d",&t);
    assert(t>=1 && t<=3);
    while(t--)
    {
        memset(p,0,sizeof(p));
        memset(isnode,0,sizeof(isnode));
        int i,n,j;
        scanf("%d",&n);
        assert(n>=1 && n<=100000);
        for(i = 0;i < n;i++)
        {
            scanf("%d %d",&x,&y);
            assert(x>=1 && x<=100000);
            assert(y>=0 && y<=100000);
            a[i] = x;
            if(y!=0)
                assert(isnode[y]==1);
            assert(isnode[x]==0);
            isnode[x] = 1;
            p[x][0] = y;
        }
        int lgn = (int)(log(n)/log(2))+1;
        for(j = 1;j<=lgn;j++)
        {
            for(i = 0;i < n;i++)
            {
                p[a[i]][j] = p[p[a[i]][j-1]][j-1];
            }
        }
    
        scanf("%d",&q);
        assert(q>0 && q<=100000);
        for(i = 0;i < q;i++)
        {
            scanf("%d",&ch);
            assert(ch>=0 && ch<=2);
            if(ch == 0) //Add an edge
            {
                scanf("%d %d",&x,&y);
    
                assert(y>=1 && y<=100000);
                assert(x>=1 && x<=100000);
                
                assert(isnode[x]==1);
                assert(isnode[y]==0);
                isnode[y] = 1;
                p[y][0] = x;
                j = 0;
                while(p[y][j]!=0)
                {
                    p[y][j+1] = p[p[y][j]][j];
                    j++;
                }
                while(j<=lgn)
                {
                    p[y][j] = 0;
                    j++;
                }
            }
            else if(ch == 1) //Remove an edge
            {
                scanf("%d",&x);
                assert(x>=1 && x<=100000);
                assert(isnode[x]==1);
                isnode[x] = 0;
                for(j = 0;j <= lgn;j++)
                {
                    p[x][j] = 0;
                }
            }
            else
            {
                scanf("%d %d",&x,&y);
                assert(x>=1 && x<=100000);
                assert(y>=1 && y<=100000);
                j = 0;
                while(y>0)
                {
                    if(y&1)
                        x = p[x][j];
                    y = y>>1;
                    j++;
                }
                printf("%d\n",x);
            }
        }
    }
    return 0;
}
    
```