• 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
    ", 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;
    }
    
  • 相关阅读:
    献给初学者:谈谈如何学习Linux操作系统
    Spring MVC 教程,快速入门,深入分析
    缓存、缓存算法和缓存框架简介
    计算机科学中最重要的32个算法
    12岁的少年教你用Python做小游戏
    当你输入一个网址的时候,实际会发生什么?
    java程序员从笨鸟到菜鸟之(七)一—java数据库操作
    java中的类修饰符、成员变量修饰符、方法修饰符。
    Java内存分配全面浅析
    Java知多少(19)访问修饰符(访问控制符)
  • 原文地址:https://www.cnblogs.com/spfa/p/7475423.html
Copyright © 2020-2023  润新知