zoukankan      html  css  js  c++  java
  • HDU 1890(Splay树)

    这个礼拜准备把Splay树补完,这道题被认为是一道Splay的水题,(然而像我这种入门级学习后还是搞了好久,毕竟算是第一次接触吧)。

    感觉Splay树必须要明确的一点:该树的中序遍历就是现在的序列

    这里面有一个区间翻转的操作,涉及到区间问题,Splay树的核心就是RotateTo(l-1,0),Rotate(r+1,root),就是把该区间的前一个数转到根节点,后一个数转到根节点的右节点,这是Key_Tree = ch[ch[root][1]][0]代表的就是这段区间。因为Splay树并不是线段树(非叶子节点可以代表一个区间)。Splay树的每个节点都是一个点,所以我们除了维护点的值外,我们还要维护以该点为根的子树的值(对应的也就是区间值)。

    我们在原序列两端添加两个节点。

    本题的关键就是找到第i小的点以后要把该段区间翻转以后删掉第i小的点(因为后面的操作和找到的点已经没有关系了)。然后delete操作怎么写?

    我们假设当前要寻找原序列中的第i小的点,由于我们前i-1小的点都已经删除了,所以我们只需要找当前序列的第i小的点,然后把这个节点转到ch[root][1],然后我们找这个节点的前驱。转到该节点下方,然后删掉该节点。就可以了。(具体看代码)。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <cstring>
    #define LL long long
    #define FOR(i,x,y)  for(int i = x;i < y;i ++)
    #define IFOR(i,x,y) for(int i = x;i > y;i --)
    #define Key_Tree ch[ch[root][1]][0]
    #define MAXN 110000
    
    using namespace std;
    
    int id[MAXN],n,p[MAXN],pos[MAXN];
    struct Num{
        int num;
        int id;
        bool operator < (const Num& rhs) const{
            if(num == rhs.num)  return id < rhs.id;
            return num < rhs.num;
        }
    }st[MAXN];
    
    struct SplayTree{
        int ch[MAXN][2],sz[MAXN],pre[MAXN],key[MAXN],root,tot;
        int flip[MAXN];
    
        void Rotate(int x,int kind){
            int y = pre[x];
            Push_Down(y);
            Push_Down(x);
            ch[y][!kind] = ch[x][kind];
            pre[ch[x][kind]] = y;
            if(pre[y]){
                ch[pre[y]][ch[pre[y]][1] == y] = x;
            }
            pre[x] = pre[y];
            ch[x][kind] = y;
            pre[y] = x;
            Push_Up(y);
        }
    
        void Splay(int x,int goal){
            Push_Down(x);
            while(pre[x] != goal){
                Push_Down(pre[pre[x]]); Push_Down(pre[x]);  Push_Down(x);
                if(pre[pre[x]] == goal){
                    Rotate(x,ch[pre[x]][0] == x);
                }
                else{
                    int y = pre[x];
                    int kind = (ch[pre[y]][0] == y);
                    if(ch[y][kind] == x){
                        Rotate(x,!kind);
                        Rotate(x,kind);
                    }
                    else{
                        Rotate(y,kind);
                        Rotate(x,kind);
                    }
                }
            }
            Push_Up(x);
            if(!goal)   root = x;
        }
    
        void RotateTo(int k,int goal){
            int x = root;
            Push_Down(x);
            while(sz[ch[x][0]] != k){
                if(k < sz[ch[x][0]]){
                    x = ch[x][0];
                }
                else{
                    k -= (sz[ch[x][0]]+1);
                    x = ch[x][1];
                }
                Push_Down(x);
            }
            Splay(x,goal);
        }
    
    
        //debug部分copy from hh
        void Treaval(int x) {
            if(x) {
                Treaval(ch[x][0]);
                printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size = %2d ,val = %2d 
    ",x,ch[x][0],ch[x][1],pre[x],sz[x],key[x]);
                Treaval(ch[x][1]);
            }
        }
        void debug() {printf("%d
    ",root);Treaval(root);}
        //以上debug
    
        void NewNode(int& x,int father,int k){
            x = ++tot;
            pre[x] = father;
            key[x] = k;
            ch[x][0] = ch[x][1] = 0;
            sz[x] = 1;
            flip[x] = 0;
        }
    
        void Push_Up(int x){
            sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1;
        }
    
        void Push_Down(int x){
            if(flip[x]){
                flip[ch[x][0]] ^= 1;
                flip[ch[x][1]] ^= 1;
                flip[x] = 0;
                swap(ch[x][1],ch[x][0]);
            }
        }
    
        void Build(int& x,int l,int r,int father){
            if(l > r)   return;
            int mid = (l+r) >> 1;
            NewNode(x,father,p[mid]);
            pos[mid+1] = x;
            Build(ch[x][0],l,mid-1,x);
            Build(ch[x][1],mid+1,r,x);
            Push_Up(x);
        }
    
        void Init(){
            root = tot = 0;
            ch[0][1] = ch[0][0] = pre[0] = sz[0] = 0;
            NewNode(root,0,0);
            NewNode(ch[root][1],root,0);
            sz[root] = 2;
            Build(Key_Tree,0,n-1,ch[root][1]);
            Push_Up(ch[root][1]);
            Push_Up(root);
        }
    
        void del(){
            int x = Get_Pre(ch[root][1]);
            if(x == -1){
                pre[ch[ch[root][1]][1]] = root;
                ch[root][1] = ch[ch[root][1]][1];
            }
            else{
                Splay(x,ch[root][1]);
                pre[Key_Tree] = root;
                pre[ch[ch[root][1]][1]] = Key_Tree;
                ch[Key_Tree][1] = ch[ch[root][1]][1];
                ch[root][1] = Key_Tree;
            }
        }
    
        void solve(){
            FOR(i,1,n+1){
                //debug();
                Splay(1,0);
                Splay(id[i],root);
                flip[Key_Tree] ^= 1;
                if(i == 1){printf("%d",i+sz[Key_Tree]);}
                else printf(" %d",i+sz[Key_Tree]);
                del();
            }
            printf("
    ");
        }
    
        int Get_Pre(int x){
            Push_Down(x);
            x = ch[x][0];
            while(x){
                Push_Down(x);
                while(ch[x][1]){
                    x = ch[x][1];
                    Push_Down(x);
                }
                return x;
            }
            return -1;
        }
    
        int Get_Next(int x){
            Push_Down(x);
            x = ch[x][1];
            while(x){
                Push_Down(x);
                while(ch[x][0]){
                    x = ch[x][0];
                    Push_Down(x);
                }
                return x;
            }
            return -1;
        }
    }spt;
    
    int main()
    {
        //freopen("test.in","r",stdin);
        while(~scanf("%d",&n) && n){
            FOR(i,0,n)  {scanf("%d",&st[i].num); p[i] = st[i].num; st[i].id = i+1;}
            spt.Init();
            //spt.debug();
            sort(st,st+n);
            FOR(i,1,n+1){
                id[i] = pos[st[i-1].id];
            }
            spt.solve();
        }
        return 0;
    }
    


    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    AVFrame 解析
    Mat与图像的基本概念
    linux基本操作
    Makefile 使用
    MySQL的安装与配置——详细过程
    k8s imagePullPolicy拉取策略
    K8S拉取Django项目创建pod
    Harbor单点仓库部署
    Django项目构建发布Harbor仓库
    K8S集群部署-二进制部署
  • 原文地址:https://www.cnblogs.com/hqwhqwhq/p/4811890.html
Copyright © 2011-2022 走看看