POJ 1442 Black Box

来源:互联网 发布:uploadify java demo 编辑:程序博客网 时间:2024/06/03 21:17

上了半个学期的课以后才发现,原来从来没有认真听过的数算实习才是幕后的大BOSS…每次作业的题目都虐到爆,每节课讲的数据结构都是数算课程上面简单数据结构的升级版,第一次靠自己的能力强行AC了Treap,把自己都感动了。

简单总结一下树堆的性质:

1、树堆,顾名思义就是树和堆的结合体,每个结点除了value值以外还增加了一个priority的值,是每个结点的权值,以最大堆为例,权值最大的点始终在堆的顶部,同时又满足搜索二叉树的性质。

2、在插入一个新的节点的时候,先按照搜索二叉树的性质把插入到叶子节点的位置,然后再使用堆的性质把这个节点siftup到对应的位置,这个时候的问题就在于siftup的时候不能单纯的进行交换,而是采用一种叫做旋转的操作,如图所示:
这里写图片描述
这里以右旋为例,如果X的权值比Y的权值大,就把X和Y的位置互换,然后理所应当地把B接在Y的左孩子结点上(因为B的值比X大比Y小),我在这道题目中的代码实现比较繁琐,不知道有没有更好的方案,我觉得直接模拟实现就好,也需要什么优化。

3、每个结点的权值一般是直接用随机数生成的,这样也导致我每次提交所用的时间都是不一样的= -

4、当我完成树堆的构造之后,输出第i大的数的时候采用的是中序遍历的方法,结果依然TLE(特别想掀桌子),在室友的启发之下,采用了另一种找第k大的数的方法:给每个结点增加一个变量,记录以这个节点为根节点的子树的节点个数,在寻找第k大的数的时候相当于一个在二叉树里面检索某个值的方式来实现,在debug一个多小时之后顺利AC…

#include<iostream>#include<limits.h>#include<memory.h>#include<stdlib.h>#include<cstdio>using namespace std;#define MAXM 30050struct node{    int value;    int size;    int priority;    int fa,lc,rc;};bool operator < (node a, node b){    return a.value < b.value;}int M,N;int real_i = 0;node treap[MAXM];int copy_i = 0;void Find2(int root,int k){    if(!root)        return;    if(treap[treap[root].lc].size +1 == k){        printf("%d\n",treap[root].value);        return;    }    if(treap[treap[root].lc].size >= k){        Find2(treap[root].lc,k);    }    else{        Find2(treap[root].rc,k-treap[treap[root].lc].size-1);    }}void insert(int _i,int root){    treap[root].size++;    treap[0].size = 0;    if(treap[_i].value > treap[root].value){        if(treap[root].rc){            insert(_i,treap[root].rc);        }        else{            treap[root].rc = _i;            treap[_i].fa = root;        }    }    else{        if(treap[root].lc){            insert(_i,treap[root].lc);        }        else{            treap[root].lc = _i;            treap[_i].fa = root;        }    }}void Rrot(int i,int j){    int k = treap[j].fa;    treap[i].fa = treap[j].fa;    if(treap[k].lc == j)        treap[k].lc = i;    else if(treap[k].rc == j)        treap[k].rc = i;    treap[j].lc = treap[i].rc;    treap[treap[j].lc].fa = j;    treap[i].rc = j;    treap[j].fa = i;    treap[j].size = treap[treap[j].lc].size + treap[treap[j].rc].size + 1;    treap[i].size = treap[treap[i].lc].size + treap[treap[i].rc].size + 1;}void Lrot(int i,int j){    int k = treap[j].fa;    treap[i].fa = treap[j].fa;    if(treap[k].lc == j)        treap[k].lc = i;    else if(treap[k].rc == j)        treap[k].rc = i;    treap[j].rc = treap[i].lc;    treap[treap[j].rc].fa = j;    treap[i].lc = j;    treap[j].fa = i;    treap[j].size = treap[treap[j].lc].size + treap[treap[j].rc].size + 1;    treap[i].size = treap[treap[i].lc].size + treap[treap[i].rc].size + 1;}void siftup(int i){    if(!i)        return;    int j = treap[i].fa;    if(treap[i].priority > treap[j].priority){        if(treap[j].lc == i){            Rrot(i,j);            siftup(i);        }        else if(treap[j].rc == i){            Lrot(i,j);            siftup(i);        }    }    return;}int main(){    memset(treap,0,sizeof(treap));    scanf("%d%d",&M,&N);    treap[0].priority = INT_MAX;    treap[0].value = INT_MIN;    treap[0].size = 0;    for(int i=1;i<=M;++i){        scanf("%d",&treap[i].value);        treap[i].priority = rand();    }    int mark;    int i = 1;    while(N--){        scanf("%d",&mark);        for(;i<=mark;++i){            treap[i].size = 1;            insert(i,treap[0].rc);            siftup(i);        }        real_i++;        Find2(treap[0].rc,real_i);    }    //system("pause");    return 0;}
0 0
原创粉丝点击