Challenge: Teleporters

Subdomeniu: Combinatorics (combinatorics)

Scor cont: 150.0 / 150

Submission status: Accepted

Submission score: 1.0

Submission ID: 464775848

Limbaj: cpp14

Link challenge: https://www.hackerrank.com/challenges/teleporters/problem

Cerinta

ByteLand is a large country with a tree-like road system. It has $N$ cities and $(N-1)$ unidirected roads. The capital of ByteLand is a city, numbered $1$, and all the roads go away from the capital. So people use these roads to reach any city from the capital. But it is impossible to reach the capital from a city by roads. 

To solve this problem, there is a system of teleporters. Each city has a teleporter in it. Each teleporter has a value of *strength*. Let's say, the $i$-th one has the value of *strength* equal to $A_i$. This means that by using the teleporter, you'll become $A_i$ cities close to the capital (the same as going $A_i$ roads in the capital direction). If the distance to the capital is less than $A_i$, you'll simply move to the capital instead.

The road system of ByteLand and the initial teleports' strengths will be given to you. You'll also be given $M$ queries about the teleport network in ByteLand. These queries will have one of the following forms:

- $1$ $X$ $Y$ : The strength of the teleport in the city with the number $X$ becomes equal to $Y$;

- $2$ $X$ : Please output the minimal number of teleports that needs to be used to get from the city with the number $X$ to the capital. We can use only teleports in this query, but not the roads!

Input Format

The first line of input will contain two space-separated integers $N$ and $M$.

The second line will contain $N$ space separated integers $A_1, A_2, ..., A_N$ - the initial strengths of the teleports.

The following $(N-1)$ lines will contain pairs of space separated positive integers $X$ and $Y$ with the meaning that there is a road between the cities with the numbers $X$ and $Y$.

Each of following $M$ lines will contain a query in one of the formats, described above.

**Constraints**  


1 <= N <= 100000  
1 <= M <= 100000  
1 <= A<sub>i</sub> <= 10000

Output Format

For each query of the second type, output an answer on a separate line.

Cod sursa

#include <bits/stdc++.h>

using namespace std;

#define rep(i, x, y) for(int i = x; i <= y; ++i)
#define dep(i, x, y) for(int i = x; i >= y; --i)
#define N 100005

struct bst{
    bst *l, *r, *fa;
    int size;
    
    inline void updata(){
        size = 1 + (l ? l->size : 0) + (r ? r->size : 0);
    }
    
    inline bool top(){return !fa || fa && fa->l != this && fa->r != this;}
    
    inline void zig(){
        bst *y = fa, *z = y->fa;
        y->l = r;
        if(r) r -> fa = y;
        r = y;
        y->fa = this;
        fa = z;
        if(z && z->l == y) z->l = this;
        if(z && z->r == y) z->r = this;
        y->updata();
    }
    
    inline void zag(){
        bst *y = fa, *z = y->fa;
        y->r = l;
        if(l) l->fa = y;
        l = y;
        y->fa = this;
        fa = z;
        if(z && z->l == y) z->l = this;
        if(z && z->r == y) z->r = this;
        y->updata();
    } 
} t[N];

void splay(bst *x){
    while(!x->top()){
        bst *y = x->fa, *z = y->fa;
        if(!y->top()){
            if(z->l == y){
                if(y->l == x) y->zig(), x->zig();
                else x->zag(), x->zig();
            } else{
                if(y->r == x) y->zag(), x->zag();
                else x->zig(), x->zag();
            }
        } else{
            if(y->l == x) x->zig();
            else x->zag();
        }
    }
    x->updata();
}

bst *access(bst *x){
    bst *y = NULL;
    for(; x; y = x, x = x->fa){
        splay(x);
        x->r = y;
        x->updata();
    }
    return y;
}

int n, m, x, y, son[N], Next[N << 1], ed[N << 1], w[N], f[N][30];

void dfs(int x, int fa){
    f[x][0] = fa;
    rep(i, 1, 20) f[x][i] = f[f[x][i - 1]][i - 1];
    for(int j = son[x]; j; j = Next[j])
        if(ed[j] ^ fa){
            t[ed[j]].fa = t + x;
            dfs(ed[j], x);
        }
}

int jump(int x,int w){
    dep(i, 20, 0) if(1 << i < w){
        w -= 1 << i;
        x = f[x][i];
    }
    x = f[x][0];
    if(!x) x = 1;
    return x;
}

bst *Right(bst *x){while(x->r) x = x->r; return x;}

void reset_w(int x,int w){
    int p = jump(x, w);
    bst *y = t + x;
    access(y);
    splay(y);
    access(Right(y->l));
    splay(y);
    y->fa = t + p;
}

int main(){
    scanf("%d%d", &n, &m);
    rep(i, 1, n) scanf("%d", w + i);
    rep(i, 2, n){
        scanf("%d%d", &x, &y);
        Next[i] = son[x], son[x] = i, ed[i] = y;
        Next[i + n] = son[y], son[y] = i + n, ed[i + n] = x;
    }
    rep(i, 1, n) t[i].size = 1;
    dfs(1, 0);
    rep(i, 2, n)
        reset_w(i, w[i]);
    while(m--){
        int opt;
        scanf("%d%d", &opt, &x);
        if(opt == 1){
            scanf("%d", &y);
            if(x ^ 1) reset_w(x, y);
        } else{
            bst *v = access(t + x);
            printf("%d\n", v->size - 1);
        }
    }
}
HackerRank Combinatorics – Teleporters