洛谷 - P3369 普通平衡树


传送门:洛谷 - P3369

题目描述

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

  1. 插入$x$
  2. 删除$x$,如果有多个数,删除一个
  3. 查询$x$的排名
  4. 查询排名为$x$的数
  5. 查询$x$的前驱
  6. 查询$x$的后继

输入描述

第一行为 $n$,表示操作的个数,下面 $n$ 行每行有两个数 $opt$ 和 $x$,$opt$ 表示操作的序号$( 1≤opt≤6 )$

输出描述

输出对应的答案

思路分析

按权值分裂

样例输入

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

样例输出

106465
84185
492737

Splay代码

#include <bits/stdc++.h>
#define fi first
#define se second
#define ll long long
#define pb push_back
#define mp make_pair
#define fun function
#define sz(x) (x).size()
#define lowbit(x) (x)&(-x)
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))

namespace FastIO {
#define BUF_SIZE 100000
#define OUT_SIZE 100000
    bool IOerror=0;
    inline char nc() {
        static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
        if(p1==pend) {
            p1=buf;
            pend=buf+fread(buf,1,BUF_SIZE,stdin);
            if(pend==p1) {
                IOerror=1;
                return -1;
            }
        }
        return *p1++;
    }
    inline bool blank(char ch) {
        return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';
    }
    template<class T> inline bool read(T &x) {
        bool sign=0;
        char ch=nc();
        x=0;
        for(; blank(ch); ch=nc());
        if(IOerror)return false;
        if(ch=='-')sign=1,ch=nc();
        for(; ch>='0'&&ch<='9'; ch=nc())x=x*10+ch-'0';
        if(sign)x=-x;
        return true;
    }
    template<class T,class... U>bool read(T& h,U&... t) {
        return read(h)&&read(t...);
    }
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace std;
using namespace FastIO;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

const int INF = 0x3f3f3f3f;
const int N = 1e6+10;

struct node {
    int siz,fa,sum,val,ch[2];
    void clear() {
        siz=fa=sum=val=ch[0]=ch[1]=0;
    }
} tree[N];

int root,cnt;

#define ls tree[x].ch[0]
#define rs tree[x].ch[1]
#define ident(x,f) tree[f].ch[1]==x

void pp(int x) {
    tree[x].siz=tree[ls].siz+tree[rs].siz+tree[x].sum;
}

void connect(int x,int f,int s) {
    tree[f].ch[s]=x;
    tree[x].fa=f;
}

void rotate(int x) {
    int f=tree[x].fa;
    int ff=tree[f].fa;
    int fs=ident(x,f);
    int ffs=ident(f,ff);
    connect(tree[x].ch[fs^1],f,fs);
    connect(x,ff,ffs);
    connect(f,x,fs^1);
    pp(f);
    pp(x);
}

void splay(int x,int top) {
    if(!top) root=x;
    while(tree[x].fa!=top) {
        int f=tree[x].fa;
        int ff=tree[f].fa;
        if(ff!=top) ident(x,f)^ident(f,ff) ? rotate(x):rotate(f);
        rotate(x);
    }
}

void newnode(int &x,int fa,int val) {
    x = ++cnt;
    tree[x].clear();
    tree[x].fa=fa;
    tree[x].val=val;
    tree[x].siz=tree[x].sum=1;
}

void delnode(int x) {
    splay(x,0);
    if(tree[x].sum>1) {
        tree[x].sum--;
        return ;
    }
    if(tree[x].ch[1]) {
        int p = tree[x].ch[1];
        while(tree[p].ch[0]) p=tree[p].ch[0];
        splay(p,x);
        connect(tree[x].ch[0],p,0);
        root=p;
        tree[root].fa=0;
        pp(root);
    } else {
        root=tree[x].ch[0];
        tree[root].fa=0;
    }
}

void ins(int &x,int fa,int val) {
    if(!x) {
        newnode(x,fa,val);
        splay(x,0);
    } else if(val<tree[x].val) {
        ins(ls,x,val);
    } else if(val>tree[x].val) {
        ins(rs,x,val);
    } else {
        tree[x].sum++;
        splay(x,0);
    }
}

void del(int x,int val) {
    if(val>tree[x].val) del(rs,val);
    else if(val<tree[x].val) del(ls,val);
    else delnode(x);
}

int getrank(int val) {
    int x = root;
    int rank = 1;
    while(x) {
        if(tree[x].val == val) {
            rank+=tree[ls].siz;
            splay(x,0);
            break;
        }
        if(val > tree[x].val) {
            rank+=tree[ls].siz+tree[x].sum;
            x=tree[x].ch[1];
        } else {
            x=tree[x].ch[0];
        }
    }
    return rank;
}

int getnum(int rank) {
    int x=root;
    while(x) {
        int lsiz = tree[ls].siz;
        if(lsiz+1 <=rank && rank<=lsiz+tree[x].sum) {
            splay(x,0);
            break;
        }
        if(lsiz<rank) {
            rank -=lsiz+tree[x].sum;
            x=tree[x].ch[1];
        } else {
            x=tree[x].ch[0];
        }
    }
    return tree[x].val;
}

void print(int x) {
    printf("%d\n",x);
}


int main() {

#ifdef xiaofan
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
#endif

    int T;
    read(T);
    while(T--) {
        int op,x;
        read(op,x);
        switch(op) {
            case 1:
                ins(root,0,x);
                break;
            case 2:
                del(root,x);
                break;
            case 3:
                print(getrank(x));
                break;
            case 4:
                print(getnum(x));
                break;
            case 5:
                print(getnum(getrank(x)-1));
                break;
            case 6:
                print(getnum(getrank(x+1)));
                break;
        }
    }



    return 0;
}

fhq treap代码

#include <functional>
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <iomanip>
#include <vector>
#include <string>
#include <cstdio>
#include <queue>
#include <stack>
#include <cmath>
#include <map>
#include <set>
#if __cplusplus >= 201103L
#include <unordered_map>
#include <unordered_set>
#endif
#define ls x<<1
#define rs x<<1|1
#define fi first
#define se second
#define ll long long
#define pb push_back
#define mp make_pair
#define fun function
#define vi vector<int>
#define lowbit(x) x&(-x)
#define pii pair<int,int>
#define all(x) x.begin(),x.end()
#define mem(a,b) memset(a,b,sizeof(a))
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);cout.tie(0);

using namespace std;

const int INF = 0x3f3f3f3f;
const int N= 1e5+10;

struct ndoe {
    int l,r;
    int key,val;
    int size;
} tree[N];

int cnt,root;

int newnode(int val) {
    tree[++cnt].val=val;
    tree[cnt].key=rand();
    tree[cnt].size=1;
    return cnt;
}

void update(int now) {
    tree[now].size=tree[tree[now].l].size+tree[tree[now].r].size+1;
}

void split(int now,int val,int &x,int &y) {
    if(!now) x=y=0;
    else {
        if(tree[now].val<=val) {
            x=now;
            split(tree[now].r,val,tree[x].r,y);
        } else {
            y=now;
            split(tree[now].l,val,x,tree[y].l);
        }
        update(now);
    }
}

int merge(int x,int y) {
    if(!x||!y)
        return x+y;
    if(tree[x].key>tree[y].key) {
        tree[x].r=merge(tree[x].r,y);
        update(x);
        return x;
    } else {
        tree[y].l=merge(x,tree[y].l);
        update(y);
        return y;
    }
}

int x,y,z;

void ins(int val) {
    split(root,val,x,y);
    root=merge(merge(x,newnode(val)),y);
}

void del(int val) {
    split(root,val,x,z);
    split(x,val-1,x,y);
    y=merge(tree[y].l,tree[y].r);
    root=merge(merge(x,y),z);
}

void getrank(int val) {
    split(root,val-1,x,y);
    cout<<tree[x].size+1<<endl;
    root=merge(x,y);
}

void getnum(int rank) {
    int now=root;
    while(now) {
        if(tree[tree[now].l].size+1==rank)
            break;
        else if(tree[tree[now].l].size>=rank)
            now=tree[now].l;
        else {
            rank-=tree[tree[now].l].size+1;
            now=tree[now].r;
        }
    }
    cout<<tree[now].val<<endl;
}

void pre(int val) {
    split(root,val-1,x,y);
    int now=x;
    while(tree[now].r)
        now=tree[now].r;
    cout<<tree[now].val<<endl;
    root=merge(x,y);
}

void nxt(int val) {
    split(root,val,x,y);
    int now=y;
    while(tree[now].l)
        now=tree[now].l;
    cout<<tree[now].val<<endl;
    root=merge(x,y);
}


int main() {
    IOS;
#ifdef xiaofan
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
#endif
    int t;
    cin>>t;
    while(t--) {
        int opt,x;
        cin>>opt>>x;
        switch(opt) {
            case 1:
                ins(x);
                break;
            case 2:
                del(x);
                break;
            case 3:
                getrank(x);
                break;
            case 4:
                getnum(x);
                break;
            case 5:
                pre(x);
                break;
            case 6:
                nxt(x);
                break;
        }
    }




    return 0;
}

文章作者: 小凡
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小凡 !
评论
  目录
隐藏
{% if theme.sakura.enable %}{% endif %}