您的位置:首页 > 其它

poj 1442 Black Box(trap模板 求整个序列的第k大

2015-09-28 21:23 351 查看
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<vector>
using namespace std;
const int maxn = 3*1e4 + 10;
struct Node
{
    Node* ch[2];
    int r, v, s;//r为优先级  v权值  s以当前节点为根的子树的节点个数
    Node(int v) : v(v)
    {
        ch[0] = ch[1] = NULL;
        r = rand();
        s = 1;
    }
    bool operator < (const Node& rhs) const
    {
        return r < rhs.r;
    }
    int cmp(int x) const
    {
        if(x == v)
            return -1;
        return x<v? 0 : 1;
    }
    void maintain()//统计节点的个数
    {
        s = 1;
        if(ch[0] != NULL)
            s += ch[0]->s;
        if(ch[1] != NULL)
            s += ch[1]->s;
    }
};
void rotate_(Node* &o, int d)//旋转函数
{
    Node* k = o->ch[d^1];
    o->ch[d^1] = k->ch[d];
    k->ch[d] = o;
    o->maintain();
    k->maintain();
    o = k;
}
void insert_(Node* &o, int x)//插入函数
{
    if(o == NULL)
        o = new Node(x);
    else
    {
        int d = (x < o->v? 0 : 1);
        insert_(o->ch[d], x);
        if(o->ch[d]->r > o->r)
            rotate_(o, d^1);
    }
    o->maintain();
}
void remove_(Node* &o, int x)//删除节点函数
{
    int d = o->cmp(x);
    if(d == -1)
    {
        Node* u = o;
        if(o->ch[0]!=NULL && o->ch[1]!=NULL)
        {
            int d2 = (o->ch[0]->r > o->ch[1]->r? 1 : 0);
            rotate_(o, d2);
            remove_(o->ch[d2], x);
        }
        else
        {
            if(o->ch[0] == NULL)
                o = o->ch[1];
            else
                o = o->ch[0];
        }
        delete(u);
    }
    else
    {
        remove_(o->ch[d], x);
    }
    if(o != NULL)//不能缺少, 当treap可能为空。
        o->maintain();
}
int kth(Node* o, int k)//求名次
{
    if(o==NULL || k<=0 || k>o->s)
        return 0;
    int s = (o->ch[0]==NULL? 0 : o->ch[0]->s);
    if(k == s+1)
        return o->v;
    else if(k <= s)
        return kth(o->ch[0], k);
    else
        return kth(o->ch[1], k-s-1);
}
void removetree(Node* &x)//释放内存函数
{
    if(x->ch[0] != NULL)
        removetree(x->ch[0]);
    if(x->ch[1] != NULL)
        removetree(x->ch[1]);
    delete x;
    x = NULL;//不能缺少, delet之后, 指针指向的内存被释放, 但指针还存在,所以要赋为空。
}
int s[maxn];
int main()
{
    int n, m, c , cc, p;
    Node* root;
    while(~scanf("%d%d", &n, &m))
    {
        root = NULL;
        for(int i = 0; i < n; i++)
            scanf("%d", &s[i]);
        c = cc = 0;
        for(int i = 0; i < m; i++)
        {
            scanf("%d", &p);
            while(c < p)
            {
                insert_(root, s[c++]);

            }
            int ans = kth(root, ++cc);
            printf("%d\n", ans);
        }
        removetree(root);//释放treap树, 不然可能会超内存。
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: