【bzoj2002】 [Hnoi2010]Bounce 弹飞绵羊

非常裸的裸题……
很明显每个点跳到的点的编号一定大于当前点,那么整个跳的图就形成了一个树结构,每个点的父亲节点定义为min(i+k,n)
这样搞之后,操作1就是查询某个点的深度,操作2就是换父亲
大概可以用dfs序搞
/ 这个坑以后再填好了 /
反正只有换父亲嘛。。。来发lct就好啦2333
作死地写了单旋然后T掉了= =

#include 
using namespace std;
#define For(i,a,b) for(int i=a;i
#define lc ch[u][0]
#define rc ch[u][1]
#define maxn 200003

inline int rd() {
    char c = getchar();
    while (!isdigit(c)) c = getchar() ; int x = c - '0';
    while (isdigit(c = getchar())) x = x * 10 + c - '0';
    return x;
}

typedef int arr[maxn];

arr fa , size , rv , sta;

int ch[maxn][2] , top , n , m;

inline bool isrt(int u) { return (ch[fa[u]][0] != u) && (ch[fa[u]][1] != u) ; }

inline void mt(int u) { if (u) size[u] = 1 + (lc ? size[lc] : 0) + (rc ? size[rc] : 0) ; }

inline void ps(int u) { if (u && rv[u]) swap(lc , rc) , rv[lc] ^= 1 , rv[rc] ^= 1 , rv[u] = 0; }

inline void rot(int u) {
    int f = fa[u] , g = fa[f] , l , r;
    l = (ch[f][1] == u) , r = l ^ 1;
    if (!isrt(f)) ch[g][ch[g][1] == f] = u;
    fa[u] = g , fa[f] = u;if (ch[u][r]) fa[ch[u][r]] = f;
    ch[f][l] = ch[u][r] , ch[u][r] = f;
    mt(f) , mt(u);
}

inline void clear(int u) {
    for(sta[top ++] = u;!isrt(u);u = fa[u]) sta[top ++] = fa[u];
    for(;top;) ps(sta[-- top]);
}

inline void splay(int u) {
    for(clear(u);!isrt(u);rot(u)) {
        int f = fa[u] , g = fa[f];
        if (!isrt(f)) rot(((ch[f][1] == u) ^ (ch[g][1] == f)) ? u : f);
    }
    mt(u);
}

inline void access(int u) {
    int v = u;
    for(int t = 0;u;t = u , u = fa[u])
        splay(u) , rc = t ;
    splay(v);
}

inline void mkrt(int u) { access(u) ; rv[u] ^= 1 ; ps(u) ; }

inline void link(int u , int v) { mkrt(u) , fa[u] = v ; }

inline void cut(int u) {
    mkrt(n + 1);
    access(u);
    fa[lc] = 0 , lc = 0 , mt(u);
}

inline int get_dep(int u) {
    mkrt(u);
    access(n + 1);
    return size[n + 1] - 1;
}

inline int get_par(int u , int k) { u += k ; if (u > n) u = n + 1 ; return u ; }

int main() {
    #ifndef ONLINE_JUDGE
        freopen("data.txt" , "r" , stdin);
        freopen("data.out" , "w" , stdout);
    #endif
    n = rd();
    For(i , 1 , n + 1) link(i , get_par(i , rd()));
    m = rd();
    For(i , 0 , m) {
        int a = rd() , b = rd() + 1 , c;
        if (a == 2) {
            c = rd();
            cut(b);
            link(b , get_par(b , c));
        } else
            printf("%d\n" , get_dep(b));
    }
    return 0;
}

你可能感兴趣的:(树,LCT,水题)