BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 动态树

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002

题意:加边,删边,查询到根的距离。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200010;
int ch[maxn][2], pre[maxn], rev[maxn], Next[maxn];
int size[maxn];
bool rt[maxn];
void Update_Rev(int r){
    if(!r) return;
    swap(ch[r][0], ch[r][1]);
    rev[r] ^= 1;
}
void push_down(int r){
    if(rev[r]){
        Update_Rev(ch[r][0]);
        Update_Rev(ch[r][1]);
        rev[r] = 0;
    }
}
void push_up(int r){
    size[r] = size[ch[r][0]]+size[ch[r][1]]+1;
}
void Rotate(int x){
    int y = pre[x], kind = ch[y][1] == x;
    ch[y][kind] = ch[x][!kind];
    pre[ch[y][kind]] = y;
    pre[x] = pre[y];
    pre[y] = x;
    ch[x][!kind] = y;
    if(rt[y])
        rt[y] = false, rt[x] = true;
    else
        ch[pre[x]][ch[pre[x]][1]==y]=x;
    push_up(y);
}
void P(int r){
    if(!rt[r]) P(pre[r]);
    push_down(r);
}
void Splay(int r){
    P(r);
    while(!rt[r]){
        int f = pre[r], ff = pre[f];
        if(rt[f])
            Rotate(r);
        else if((ch[ff][1]==f)==(ch[f][1]==r))
            Rotate(f), Rotate(r);
        else Rotate(r), Rotate(r);
    }
    push_up(r);
}
int Access(int x){
    int y = 0;
    for(;x;x=pre[y=x]){
        Splay(x);
        rt[ch[x][1]] = true, rt[ch[x][1]=y] = false;
        push_up(x);
    }
    return y;
}
void mroot(int r){
    Access(r);
    Splay(r);
    Update_Rev(r);
}
void link(int u, int v){
    mroot(u);
    pre[u] = v;
}
void cut(int u, int v){
    mroot(u);
    Splay(v);
    pre[ch[v][0]] = pre[v];
    pre[v] = 0;
    rt[ch[v][0]] = true;
    ch[v][0] = 0;
    push_up(v);
}
int n, m;
int main()
{
    scanf("%d", &n);
    for(int i=0; i<=n+1; i++){
        pre[i]=0;
        ch[i][0]=ch[i][1]=0;
        rev[i]=0;
        rt[i] = true;
        size[i] = 0;
    }
    for(int i=1,t; i<=n; i++){
        scanf("%d", &t);
        t = min(i+t, n+1);
        pre[i] = Next[i] = t;
        size[i] = 1;
    }
    size[n+1] = 1;
    scanf("%d", &m);
    int op, x, y;
    for(int i=1; i<=m; i++){
        scanf("%d%d", &op,&x);
        x++;
        if(op==1){
            mroot(n+1);
            Access(x);
            Splay(x);
            printf("%d\n", size[ch[x][0]]);
        }
        else{
            scanf("%d", &y);
            y = min(x+y,n+1);
            cut(x,Next[x]);
            link(x,y);
            Next[x]=y;
        }
    }
    return 0;
}

 

posted @ 2017-09-04 20:15  zxycoder  阅读(134)  评论(0编辑  收藏  举报