zoukankan      html  css  js  c++  java
  • [模板]普通平衡树

    【模板】普通平衡树

    题目链接

    题目描述

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

    1. 插入 xx 数
    2. 删除 xx 数(若有多个相同的数,因只删除一个)
    3. 查询 xx 数的排名(排名定义为比当前数小的数的个数 +1+1 。若有多个相同的数,因输出最小的排名)
    4. 查询排名为 xx 的数
    5. 求 xx 的前驱(前驱定义为小于 xx ,且最大的数)
    6. 求 xx 的后继(后继定义为大于 xx ,且最小的数)

    输入输出格式

    输入格式:

    第一行为 nn ,表示操作的个数,下面 nn 行每行有两个数 optopt 和 xx , optopt 表示操作的序号( 1 leq opt leq 61≤opt≤6 )

    输出格式:

    对于操作 3,4,5,63,4,5,6 每行输出一个数,表示对应答案

    输入输出样例

    输入样例#1:

    10
    1 106465
    4 1
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598

    输出样例#1:

    106465
    84185
    492737

    说明

    时空限制:1000ms,128M

    1.n的数据范围: (n≤100000)

    2.每个数的数据范围: ([-10^7,10^7])

    替罪羊树

    学习总结

    #include<bits/stdc++.h>
    using namespace std;
    int read()
    {
        int x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*w;
    }
    double alpha=0.75;
    int n,x,opt,cnt,root,need,top;
    int s[100010];
    struct node{
        int son[2],v,die,s;
    }t[100010];
    bool exist(int k){return (t[k].die^1);}
    bool bad(int k)
    {
        int k1=t[k].son[0],k2=t[k].son[1];
        return (double)max(t[k1].s,t[k2].s)>=(double)t[k].s*alpha;
    }
    void dfs(int k)
    {
        if(!k) return;
        dfs(t[k].son[0]);if(!t[k].die)s[++top]=k;dfs(t[k].son[1]);
    }
    void build(int &k,int l,int r)
    {
        if(l>r)return;int mid=(l+r)/2;k=s[mid];
        if(l==r)
        {
            t[k].s=1;t[k].son[0]=t[k].son[1]=t[k].die=0;return;
        }
        if(l<mid) build(t[k].son[0],l,mid-1);else t[k].son[0]=0;
        if(r>mid) build(t[k].son[1],mid+1,r);else t[k].son[1]=0;
        t[k].s=t[t[k].son[0]].s+t[t[k].son[1]].s+1;return;
    }
    void rebuild(int &k)
    {
        top=0;dfs(k);if(top)build(k,1,top);
    }
    void insert(int &k,int v)
    {
        if(!k)
        {
            k=++cnt;t[k].v=v;t[k].s=1;return;
        }
        if(v<=t[k].v) insert(t[k].son[0],v);
        else insert(t[k].son[1],v);
        int k1=t[k].son[0],k2=t[k].son[1];
        t[k].s=t[k1].s+t[k2].s+exist(k);
        if(!bad(k))
        {
            if(need)
            {
                if(need==t[k].son[0]) rebuild(t[k].son[0]);
                else rebuild(t[k].son[1]);
            }
            need=0;
        }
        else need=k;
    }
    void delet(int k,int v)
    {
        if(!k) return;
        int k1=t[k].son[0],k2=t[k].son[1];
        if(!t[k].die&&t[k1].s+1==v){t[k].die=1;t[k].s--;return;}
        if(t[k1].s>=v) delet(k1,v);
        else delet(k2,v-t[k1].s-exist(k));
        t[k].s=t[k1].s+t[k2].s+exist(k);
        if(!bad(k))
        {
            if(need)
            {
                if(need==t[k].son[0]) rebuild(t[k].son[0]);
                else rebuild(t[k].son[1]);
            }
            need=0;
        }
        else need=k;
    }
    int getrank(int k,int v)
    {
        if(!k) return 0;
        int k1=t[k].son[0],k2=t[k].son[1];
        if(t[k].v<v) return t[k1].s+exist(k)+getrank(k2,v);
        return getrank(k1,v);
    }
    int kth(int k,int v)
    {
        if(!k) return 0;
        int k1=t[k].son[0],k2=t[k].son[1];
        if(!t[k].die&&t[k1].s+1==v) return t[k].v;
        if(t[k1].s>=v) return kth(k1,v);
        return kth(k2,v-t[k1].s-exist(k));
    }
    int main()
    {
        n=read();
        for(int i=1;i<=n;i++)
        {
            opt=read();x=read();
            if(opt==1){insert(root,x);if(need)rebuild(root),need=0;}
            if(opt==2)
            {
                int d=getrank(root,x)+1;
                delet(root,d);
                if(need)rebuild(root),need=0;
            }
            if(opt==3) printf("%d
    ",getrank(root,x)+1);
            if(opt==4) printf("%d
    ",kth(root,x));
            if(opt==5) printf("%d
    ",kth(root,getrank(root,x)));
            if(opt==6) printf("%d
    ",kth(root,getrank(root,x+1)+1));
        }
    }
    

    Splay

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0') {if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*w;
    }
    int root,cnt,inf=2100000000;
    struct node{
    int fa,son[2],size,cnt,v;
    }tree[100010];
    void push_up(int);
    void splay(int,int);
    bool get(int);
    void rotate(int);
    void insert(int);
    void delet(int);
    int getrank(int);
    int getsum(int);
    int find(int);
    int kth(int,int);
    int main()
    {
        int n=read(),opt,x;
        insert(inf);insert(-inf);
        for(int i=1;i<=n;i++)
        {
            opt=read();x=read();
            if(opt==1) insert(x);
            else if(opt==2) delet(x);
            else if(opt==3) printf("%d
    ",getrank(x));
            else if(opt==4) printf("%d
    ",getsum(x+1));
            else if(opt==5) printf("%d
    ",tree[kth(x,0)].v);
            else if(opt==6) printf("%d
    ",tree[kth(x,1)].v);
        }
    }
    void push_up(int k)
    {
        tree[k].size=tree[tree[k].son[0]].size+tree[tree[k].son[1]].size+tree[k].cnt;
    }
    bool get(int k)
    {
        return k==tree[tree[k].fa].son[1];
    }
    void rotate(int k)
    {
        int fa=tree[k].fa,gfa=tree[fa].fa,d1=get(k),d2=get(fa);
        tree[fa].son[d1]=tree[k].son[d1^1];tree[tree[k].son[d1^1]].fa=fa;
        tree[k].son[d1^1]=fa;tree[fa].fa=k;
        tree[gfa].son[d2]=k;tree[k].fa=gfa;
        push_up(fa);push_up(k);
    }
    void splay(int k,int goal)
    {
        while(tree[k].fa!=goal)
        {
            int fa=tree[k].fa,gfa=tree[fa].fa,d1=get(k),d2=get(fa);
            if(gfa!=goal)
            {
                if(d1==d2) rotate(fa);
                else rotate(k);
            }
            rotate(k);
        }
        if(goal==0) root=k;
    }
    void insert(int k)
    {
        int now=root,fa=0;
        while(tree[now].v!=k&&now)
        fa=now,now=tree[now].son[k>tree[now].v];
        if(now) 
        tree[now].cnt++;
        else
        {
            now=++cnt;
            if(fa) tree[fa].son[k>tree[fa].v]=now;
            tree[now].v=k;
            tree[now].fa=fa;
            tree[now].cnt=1;
            tree[now].size=1;
        }
        splay(now,0);
    }
    void delet(int k)
    {
        int last=kth(k,0),next=kth(k,1);
        splay(last,0);splay(next,last);
        if(tree[tree[next].son[0]].cnt>1) 
        {
            tree[tree[next].son[0]].cnt--;
            splay(tree[next].son[0],0);
        }
        else tree[next].son[0]=0;
    }
    int find(int k)
    {
        int now=root;
        while(tree[now].v!=k&&tree[now].son[tree[now].v<k])
        now=tree[now].son[tree[now].v<k];
        return now;
    }
    int getrank(int k)
    {
        splay(find(k),0);
        return tree[tree[root].son[0]].size;
    }
    int getsum(int k)
    {
        int now=root;
        while(1)
        {
            if(k>tree[tree[now].son[0]].size&&k<=tree[tree[now].son[0]].size+tree[now].cnt) return tree[now].v;
            else if(k>tree[tree[now].son[0]].size+tree[now].cnt) k-=tree[tree[now].son[0]].size+tree[now].cnt,now=tree[now].son[1];
            else now=tree[now].son[0];
        }
    }
    int kth(int k,int judge)
    {
        int x=find(k);
        splay(x,0);
        if(judge==0&&k>tree[root].v) return root;
        if(judge==1&&k<tree[root].v) return root;
        int now=tree[root].son[judge];
        while(tree[now].son[judge^1])
        now=tree[now].son[judge^1];
        return now;
    }
    
  • 相关阅读:
    缓存概述
    进程Process
    MVC系统过滤器、自定义过滤器
    暂无,进程那篇深度不够
    SeasLog 与 monolog 日志系统的区别,SeasLog安装步骤
    阿里面试官:说一下从url输入到返回请求的过程,问的难度就是不一样!
    [技术分享]OSI七层模型详解
    Mysql引擎介绍及InnoDB逻辑存储结构
    Paypal 实现自动订阅
    PayPal 支付Checkout 收银台和 Subscription 订阅计划全过程分享
  • 原文地址:https://www.cnblogs.com/lsgjcya/p/9349229.html
Copyright © 2011-2022 走看看