POJ 2985 Treap平衡树(求第k大的元素)

这题也能够用树状数组做,并且树状数组姿势更加优美。代码更加少,只是这个Treap树就是求第K大元素的专家……所以速度比較快。

这个也是从那本红书上拿的模板……自己找了资料百度了好久,才理解这个Treap主要的知识,要是自己写真的得写到什么时候啊!。。

然后输入的时候是写n-k+1反着找的,就是这里又浪费了好多时间debug。唉……

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <list>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define sc(a,b) scanf("%d%d",&a,&b)
#define pri(a) printf("%d
",a)
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define MM 440004
#define MN 1008
#define INF 100000007
#define eps 1e-7
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
struct Treap
{
    int root,treapCnt,key[MM],priority[MM],childs[MM][2],cnt[MM],size[MM];
    Treap()
    {
        root=0;
        treapCnt=1;
        priority[0]=INF;
        size[0]=0;
    }
    void update(int x)
    {
        size[x]=size[childs[x][0]]+cnt[x]+size[childs[x][1]];
    }
    void rotate(int &x,int t)
    {
        int y=childs[x][t];
        childs[x][t]=childs[y][1-t];
        childs[y][1-t]=x;
        update(x);
        update(y);
        x=y;
    }
    void _insert(int &x,int k)
    {
        if(x)
        {
            if(key[x]==k) cnt[x]++;
            else
            {
                int t=key[x]<k;
                _insert(childs[x][t],k);
                if(priority[childs[x][t]]<priority[x]) rotate(x,t);
            }
        }
        else
        {
            x=treapCnt++;
            key[x]=k;
            cnt[x]=1;
            priority[x]=rand();
            childs[x][0]=childs[x][1]=0;
        }
        update(x);
    }
    void _erase(int &x,int k)
    {
        if(key[x]==k)
        {
            if(cnt[x]>1) cnt[x]--;
            else
            {
                if(childs[x][0]==0&&childs[x][1]==0)
                {
                    x=0;
                    return ;
                }
                int t=priority[childs[x][0]]>priority[childs[x][1]];
                rotate(x,t);
                _erase(x,k);
            }
        }
        else _erase(childs[x][key[x]<k],k);
        update(x);
    }
    int _getkth(int &x,int k)
    {
        if(k<=size[childs[x][0]]) return _getkth(childs[x][0],k);
        k-=size[childs[x][0]]+cnt[x];
        if(k<=0) return key[x];
        return _getkth(childs[x][1],k);
    }
    void insert(int k)
    {
        _insert(root,k);
    }
    void erase(int k)
    {
        _erase(root,k);
    }
    int getkth(int k)
    {
        return _getkth(root,k);
    }
}treap;
int f[MM],a[MM];
int find(int x)
{
    return f[x]==x?x:f[x]=find(f[x]);
}
int main()
{
    int n,m,i,k,x,y;
    sc(n,m);
    for(i=0;i<=n;i++) f[i]=i,a[i]=1; //初始每一个区间的元素都是1咯。自身嘛。
    for(i=1;i<=n;i++) treap.insert(1);
    for(i=1;i<=m;i++)
    {
        sca(k);
        if(!k)
        {
            sc(x,y);
            x=find(x),y=find(y);
            if(x==y) continue;
            f[y]=x;
            treap.erase(a[x]); //先把这两个区间删除了
            treap.erase(a[y]);
            a[x]+=a[y];  //区间合并。元素相加
            treap.insert(a[x]); //然后把合并的加到treap平衡树中
            n--;  //合并区间,总区间少1
        }
        else
        {
            sca(k);
            pri(treap.getkth(n-k+1)); //反着找
        }
    }
    return 0;
}


原文地址:https://www.cnblogs.com/yangykaifa/p/6800308.html