【HDU 6394】暑期多校day7 Tree (LCT、倍增LCA)

题目大意

给出一个有根树,每一个结点有一个值 ki ,表示到达这个点的的石子可以向根跳 ki 步,现在有两种操作:1)改变一个点的 ki 值,2)查询向一个点丢石子时,石子弹几次才会走出树。


解题思路

这道题其实就是弹飞绵羊那道题的升级版,两种操作可以分别被理解为:改变某个节点的父节点,查询某个结点到根节点的距离。感觉当场只有100人过掉有点少了吧。


代码

#include <bits/stdc++.h>
using namespace std;

const int maxn=int(1e5)+11, OUT=int(1e5)+3;

struct Node {
    int key,siz;
    Node *ch[2],*fa;
    Node();
    Node(int);
    int son() {
        if(this==fa->ch[0]) return 0;
        if(this==fa->ch[1]) return 1;
        return -1;
    }
    void maintain();
}*null, node[maxn];
Node:: Node():key(-1) {
    siz=null?1:0;
    ch[0]=ch[1]=fa=null;
}
Node:: Node(int _):key(_) {
    siz=null?1:0;
    ch[0]=ch[1]=fa=null;
}
void Node:: maintain() {
    siz=ch[0]->siz+1+ch[1]->siz;
    return;
}

void Rotate(Node* cur,int dir) {
    Node* tmp=cur->ch[dir^1];
    cur->ch[dir^1]=tmp->ch[dir], tmp->ch[dir]->fa=cur;
    tmp->ch[dir]=cur;
    cur->maintain(), tmp->maintain();
    if(~cur->son()) cur->fa->ch[cur->son()]=tmp;
    tmp->fa=cur->fa, cur->fa=tmp;
    return;
}

void Splay(Node* cur) {
    while(~cur->son()) {
        int dir=cur->son();
        if(dir==cur->fa->son()) Rotate(cur->fa->fa,dir^1);
        Rotate(cur->fa,dir^1);
    }
    return;
}

void Access(Node* cur) {
    Node* tmp=null;
    while(cur!=null) {
        Splay(cur);
        cur->ch[1]=tmp, cur->maintain();
        tmp=cur, cur=cur->fa;
    }
    return;
}

void Modify(Node* x,Node* y) {
    Access(x), Splay(x);
    x->ch[0]->fa=null;
    x->ch[0]=null, x->maintain();
    x->fa=y;
    return;
}

void init_null() {
    null=new Node(-1);
    null->ch[0]=null->ch[1]=null->fa=null;
    return;
}


struct Edge {
    int to,next;
    Edge() {}
    Edge(int a,int b):to(a),next(b) {}
}eage[maxn*2];
int n;
int head[maxn], tot=0;
int dep[maxn];
int fa[maxn][30];
int a[maxn];

void add_eage(int u,int v) {
    eage[tot]=Edge(v,head[u]), head[u]=tot++;
    return;
}

void init() {
    register int i;
    tot=0;
    for(i=1;i<=n;++i) {
        head[i]=-1;
    }
    return;
}

void dfs(int u,int d) {
    register int i;
    dep[u]=d;
    for(i=1;(1<<i)<=d;++i)
        fa[u][i]=fa[fa[u][i-1]][i-1];
    for(i=head[u];~i;i=eage[i].next) {
        fa[eage[i].to][0]=u;
        dfs(eage[i].to,d+1);
    }
    return;
}
int get_fa(int u,int k) {
    if(k>dep[u]) return OUT;
    int i=0;
    for(;k;k>>=1,i++) if(k&1) u=fa[u][i];
    return u;
}

void work() {
    scanf("%d",&n);
    init();
    register int i,v;
    for(i=0;i<30;++i)
        fa[1][i]=OUT;
    for(i=2;i<=n;++i) {
        scanf("%d",&v);
        add_eage(v,i);
    }
    dfs(1,0);

    for(i=1;i<=n;++i) {
        scanf("%d",&a[i]);
        node[i]=Node(i);
        int g=get_fa(i,a[i]);
        if(g<=n) node[i].fa=&node[g]; 
    }

    int m,op,x,y;
    scanf("%d",&m);
    for(i=1;i<=m;++i) {
        scanf("%d%d",&op,&x);
        if(op==1) {
            Access(&node[x]); Splay(&node[x]);
            printf("%d\n",node[x].siz);
        } else {
            scanf("%d",&y);
            int g=get_fa(x,y);
            if(g<=n) Modify(&node[x],&node[g]);
            else Modify(&node[x],null);
        }
    }
    return;
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.txt","r",stdin);
#endif
    init_null();
    int T;
    for(scanf("%d",&T);T;T--)
        work();

    return 0;
}
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页