zoukankan      html  css  js  c++  java
  • BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊 ——Link-Cut Tree

    【题目分析】

        以前用分块的方法做过这道题目,现在再用LCT水一边,发现思路确实巧妙。

        每次弹射,可以看作在一条边上走了过去,而且很重要的性质,每一个点的出边只有一条。

        那么就很容易知道,可以用LCT维护连通性,然后把n+1这个虚点当作根,把起点旋转上去,然后n+1的深度就是结果的值。

        更进一步,由于偏爱路径只是起点到n+1,深度又改为了子树大小size的查询。

        均摊复杂度NlogN

    【代码】

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
     
    #include <set>
    #include <map>
    #include <string>
    #include <algorithm>
    #include <vector>
    #include <iostream>
    #include <queue>
     
    using namespace std;
     
    #define maxn 1000005
    #define inf (0x3f3f3f3f)
     
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while (ch<'0'||ch>'9') {if (ch=='-') f=-1; ch=getchar();}
        while (ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
     
    int fa[maxn],ch[maxn][2],siz[maxn],rev[maxn],top=0,sta[maxn];
     
    bool isroot(int x)
    {
        return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;
    }
     
    void update(int x)
    {
        siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    }
     
    void pushdown(int x)
    {
        if (rev[x])
        {
            rev[x]^=1;
            rev[ch[x][0]]^=1;
            rev[ch[x][1]]^=1;
            swap(ch[x][0],ch[x][1]);
        }
    }
     
    void rot(int x)
    {
        int y=fa[x],z=fa[y],l,r;
        if (ch[y][0]==x) l=0; else l=1;
        r=l^1;
        if (!isroot(y))
        {
            if (ch[z][0]==y) ch[z][0]=x;
            else ch[z][1]=x;
        }
        fa[x]=z; fa[y]=x; fa[ch[x][r]]=y;
        ch[y][l]=ch[x][r]; ch[x][r]=y;
        update(y); update(x);
    }
     
    void splay(int x)
    {
        int top=0; sta[++top]=x;
        for (int i=x;!isroot(i);i=fa[i]) sta[++top]=fa[i];
        while (top) pushdown(sta[top--]);
        while (!isroot(x))
        {
            int y=fa[x],z=fa[y];
            if (!isroot(y))
            {
                if (ch[y][0]==x^ch[z][0]==y) rot(x);
                else rot(y);
            }
            rot(x);
        }
    }
     
    void access(int x)
    {
        for (int t=0;x;t=x,x=fa[x])
        {
            splay(x);
            ch[x][1]=t;
            update(x);
        }
    }
     
    void makeroot(int x)
    {
        access(x);
        splay(x);
        rev[x]^=1;
    }
     
    int find(int x)
    {
        access(x);
        splay(x);
        while (ch[x][0]) x=ch[x][0];
        return x;
    }
     
    void link(int x,int y)
    {
    //  printf("link %d %d
    ",x,y);
        makeroot(x);
        fa[x]=y;
    //  update(x);update(y);
    }
     
    void cut(int x,int y)
    {
    //  printf("cut %d %d
    ",x,y);  
        makeroot(x);
        access(y);
        splay(y);
        ch[y][0]=fa[x]=0;
    //  update(x);update(y);
    }
     
    int m,n,a[maxn];
     
    int main()
    {
        n=read(); for (int i=1;i<=n;++i) a[i]=read(),link(i,min(n+1,a[i]+i));
        m=read();
        while (m--)
        {
            int opt,x,y;
            opt=read();x=read(); x++;
            switch(opt)
            {
                case 1:
    //              x=read();x++;
                    makeroot(n+1);
                    access(x);
                    splay(x);
                    printf("%d
    ",siz[x]-1);
                    break;
                case 2:
    //              x=read();x++;
                    y=read();
                    cut(x,min(n+1,a[x]+x));
                    a[x]=y;
                    link(x,min(n+1,a[x]+x));
                break;
            }
        }
    }
    

      

  • 相关阅读:
    【Leetcode】23. Merge k Sorted Lists
    【Leetcode】109. Convert Sorted List to Binary Search Tree
    【Leetcode】142.Linked List Cycle II
    【Leetcode】143. Reorder List
    【Leetcode】147. Insertion Sort List
    【Leetcode】86. Partition List
    jenkins 配置安全邮件
    python 发送安全邮件
    phpstorm 同步远程服务器代码
    phpUnit 断言
  • 原文地址:https://www.cnblogs.com/SfailSth/p/6195075.html
Copyright © 2011-2022 走看看