zoukankan      html  css  js  c++  java
  • 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;
    }
    


  • 相关阅读:
    手势
    ios提示框,自动消失
    UITableView
    UIAlertView
    微信公众号主页链接
    试用avalon2.0
    VirtualPathProvider的使用
    代码暂存 [获取二唯码并识别保存二唯码]
    提交数据url太长导致提交失败
    打通前后台
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/6800308.html
Copyright © 2011-2022 走看看