zoukankan      html  css  js  c++  java
  • 平衡二叉树之splay p1998

      splay是如何减少时间复杂度呢?让我先研读一下代码QAQ每次访问某个节点时都把它旋转到根节点.

      以下转自https://blog.csdn.net/qq_31640513/article/details/76944892

      共有三种情况.

      那不如直接上例题?(越来越懒)

     

      区间旋转怎么做啊??

      我会splay,但是好像还不够,我还会打标记!

      考虑每次区间旋转的时候,我们可以找到区间l的前驱,把他旋转到根节点,这样根节点和根节点的右子树是[1,l-1],左子树是[l,n],然后我们把r的后继旋转到根节点的右儿子,这样根节点的右儿子和右儿子的子树就是[l+1,n],根节点的右儿子的左子树即为区间[l,r],打标记走人!

      输出就简单了,dfs(root),对于当前节点x,如果有标记就把标记下传并交换左右子树,然后dfs(左儿子),然后输出x,然后dfs(右儿子).

      为什么复杂度能够保证呢?好像要用到势函数或摊还分析,告辞.

      哦差点忘了放代码了.

      

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    using namespace std;
    #define INF 2000000007
    char buf[1<<15],*fs,*ft;
    inline char getc(){
      return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:* fs++;
    }
    inline int read(){
        int This=0,F=1; char ch=getc();
        while(ch<'0'||ch>'9'){
            if(ch=='-') F=-1;
            ch=getc();
        }
        while(ch>='0'&&ch<='9'){
            This=(This<<1)+(This<<3)+ch-'0';
            ch=getc();
        }
        return This*F;
    }
    
    inline void write(int x)
    {
        if(x==0)
        {
            putchar('0');
            putchar(32);
            return;
        }
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        int num=0;char ch[16];
        while(x) ch[++num]=x%10+'0',x/=10;
        while(num) putchar(ch[num--]);
        putchar(32);
    }
    struct node{
        int l,r;
        int f,v,sz;
        bool flag;
        void set(int x)
        {
            v=x;
            //ch[0]=ch[1]=f=flag=0;
            sz=1;
        }
    }o[100010];
    int n,m,root,tot,l,r,X1,X2;
    void updata(int x)
    {
        if(!x) 
            return ;
        o[x].sz=1+o[o[x].l].sz+o[o[x].r].sz;
    }
    void PD(int x)//标记下传,旋转儿子
    {
        if (!x) return ;
        if (o[x].flag)
        {
            o[o[x].l].flag^=1;o[o[x].r].flag^=1;
            o[x].flag=0;
            int t=o[x].l;o[x].l=o[x].r;o[x].r=t;
        }
    }
    void SC(int x,int y,bool z)
    {
        if(z)
            o[x].r=y;
        else
            o[x].l=y;
        o[y].f=x;
    }
    inline bool d(int x) {return o[o[x].f].r==x;}
    void rot(int x)
    {
        int y=o[x].f,z=o[y].f,tt=d(x);
        SC(z,x,d(y));
        if(!tt)
            SC(y,o[x].r,tt);
        else
            SC(y,o[x].l,tt);
        SC(x,y,!tt);
        updata(y);
    }
    void splay(int x,int f)
    {
        PD(x);
        if (f==0) 
            root=x;
        while (o[x].f!=f)
        {
            if (o[o[x].f].f==f) {rot(x);break;}
            if (d(x)==d(o[x].f)) {rot(o[x].f);rot(x);} else {rot(x);rot(x);}
        }
        updata(x);
    }
    int build(int l,int r)
    {
        if (l>r) return 0;
        tot++;
        int x=tot,mid=(l+r)>>1;
        o[x].set(mid);
        o[x].l=build(l,mid-1);
        o[x].r=build(mid+1,r);
        o[o[x].l].f=o[o[x].r].f=x;
        updata(x);
        return x;
    }
    int find(int x,int y)
    {
        PD(x);
        if (o[o[x].l].sz+1<y) return find(o[x].r,y-1-o[o[x].l].sz);
        else if (o[o[x].l].sz+1==y) return x;
        else return find(o[x].l,y);
    }
    void dfs(int x)
    {
        PD(x);
        if (o[x].l)
            dfs(o[x].l);
        write(o[x].v);
        if (o[x].r) 
            dfs(o[x].r); 
    }
    int main()
    {
        
        //freopen("123.in","r",stdin);
        n=read();m=read();
        o[0].v=o[n+1].v=INF;
        root=build(0,n+1);
        while(m--)
        {
            l=read();r=read();
            X1=find(root,l);
            X2=find(root,r+2);
            splay(X1,0);
            splay(X2,X1);
            updata(root);
            o[o[X2].l].flag^=1;
            updata(o[X2].l);updata(X2);updata(root);
        }
        dfs(root);
        return 0;
    }
    View Code
  • 相关阅读:
    Windows10下配置单机zookeeper(连接服务器上的zookeeper)
    尚硅谷Zookeeper教程学习讲义
    腾讯云服务器在防火墙上添加可访问端口(CentOS7)
    uniPaaS 2.0新功能
    uniPaas RIA 安装与使用方法
    unipaas2.0发布了,有需要试的请与我联系QQ:79982575
    UNIPAAS抢滩Web 2.0
    最简便最快速的开发工具—Magic eDeveloper/DBMAGIC/UNIPAAS
    RIA技术的应用(UNIPAAS)
    数据库开发工具Magic教程基本操作(以Magic eDeveloper V10为例,其他版本会有差异)
  • 原文地址:https://www.cnblogs.com/qywyt/p/10363177.html
Copyright © 2011-2022 走看看