HDU 4006 The kth great number [2011 大连网络赛] [AVL树解法]

来源:互联网 发布:饭岛三智 知乎 编辑:程序博客网 时间:2024/05/18 23:25

题意:

找第K大的数惊讶


分析:

可以用STL里的priority_queue解决,这里尝试使用AVL树~生气


//AC CODE:


#include <iostream>#include <cstring>#include <cstdio>using namespace std;int delta;const int INF = 10000000;template<typename T>class AVL{public:    AVL()    {        pp = pool;        TMP = node(0,0,NULL,NULL);        MYNULL = &TMP;        roof = MYNULL;    }    void insert(T k)    {        insert(roof,k);    }    void erase(T k)    {        erase(roof,k);    }    bool empty()    {        return roof == MYNULL;    }    int findK(int k)    {        if(k <= 0)            return -INF;        return findK(roof,k);    }    struct node    {        node *lchild,*rchild;        T value;        int h,size;//h表示高度,size表示以当前节点为跟的子树有多少个节点        node() {}        node (int h,int size,node * lchild,node *rchild)        {            this->size = size;            this->h = h;            this->lchild = lchild;            this->rchild = rchild;        }    };    node* roof;private:#define max(a,b) ((a) < (b) ? (b) : (a))    static const int N = 1000000;    node* MYNULL,TMP;    //为了快速方便的求高度而设立的虚空节点    node pool[N],*pp;    int findK(node* &R,int k)    {        if(k == R->lchild->size + 1)            return R->value;        else if(k <= R->lchild->size)            return findK(R->lchild,k);        else if(k > R->size - R->rchild->size)            return findK(R->rchild,k + R->rchild->size - R->size);    }    //旋转前维护该节点的子树的height和size,然后才能根据更新的数据,判断该树是否平衡,然后旋转    //该函数维护了平衡树的数据域    void fix(node* &R)    {        R->h = max(R->rchild->h,R->lchild->h) + 1;        R->size = R->rchild->size + R->lchild->size + 1;    }    void rightsinglerotate(node* &R)//LL型旋转,单旋一次    {        node * lc = R->lchild;        R->lchild = lc->rchild;        fix(R);        lc->rchild = R;        R = lc;        fix(R);    }    void leftsinglerotate(node* &R)//RR型旋转,单选一次    {        node * rc = R->rchild;        R->rchild = rc->lchild;        fix(R);        rc->lchild = R;        R = rc;        fix(R);    }    void leftdoublerotate(node* &R)//RL型旋转,双旋    {        rightsinglerotate(R->rchild);        leftsinglerotate(R);    }    void rightdoublerotate(node* &R)//LR型旋转,双旋    {        leftsinglerotate(R->lchild);        rightsinglerotate(R);    }    void maintain(node* &R)//维护平衡    {        if(R->lchild != MYNULL)        {            if(R->lchild->lchild->h == R->rchild->h + 1)                rightsinglerotate(R);            else if(R->lchild->rchild->h == R->rchild->h + 1)                rightdoublerotate(R);        }        if(R->rchild != MYNULL)        {            if(R->rchild->rchild->h == R->lchild->h + 1)                leftsinglerotate(R);            else if(R->rchild->lchild->h == R->lchild->h + 1)                leftdoublerotate(R);        }    }    void insert(node* &R,T value)    {        if(R == MYNULL)        {            R = mynew(value);            return;        }        else if(value <= R->value)            insert(R->lchild,value);        else if(value > R->value)            insert(R->rchild,value);        fix(R);        maintain(R);    }    //找到该节点后,    //如果该节点R没有右儿子,直接删除,把他的左子树R->child接到他的父节点即可。    //如果有右儿子,那就找到他右子树中最小的元素的节点tmp,    //把他放到当前节点R->value = tmp->value。再以他的右子树为根递归的删除tmp->value;递归完右子树维护数据域。    //最后在调整树使其不失衡。    void erase(node* &R,T value)    {        if(R == MYNULL)            return;        if(R->value == value)        {            if(R->rchild == MYNULL)            {                node * tmp = R;                R = tmp->lchild;            }            else            {                node *tmp = R->rchild;                while(tmp->lchild != MYNULL)                    tmp = tmp->lchild;                R->value = tmp->value;                erase(R->rchild,tmp->value);                fix(R);            }            return;        }        else if(value < R->value)            erase(R->lchild,value);        else if(value < R->value)            erase(R->rchild,value);        fix(R);        maintain(R);    }    node* mynew(T value)    {        pp->lchild = pp->rchild = MYNULL;        pp->size = pp->h = 1;        pp->value = value;        return pp++;    }#undef max};AVL<int> avltree;int main(){    int n,k,tmp;    char cmd;    while(scanf("%d %d",&n,&k)!=EOF)    {        getchar();        while(!avltree.empty())        {            avltree.erase(avltree.roof->value);        }        for(int i=0;i<n;i++)        {            scanf("%c",&cmd);            if(cmd=='I')            {                scanf("%d",&tmp);                avltree.insert(tmp);            }            else            {                int tmp = avltree.findK(avltree.roof->size - k + 1);                if(tmp == -INF)                    printf("-1\n");                else                    printf("%d\n",tmp);            }            getchar();        }    }    return 0;}


原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 ld密码被停用了怎么办 档案被自己丢了怎么办 手机在厂里丢了怎么办 在厂里借工具丢了怎么办 导出的考勤没有姓名怎么办 退休时档案丢了怎么办 职工与企业没有劳资怎么办 去大学报道的档案袋丢失怎么办 档案入学毕业年份写错怎么办 从事业单位辞职后人事档案怎么办 老师辞职不给批怎么办 公办教师去私立学校档案怎么办 辞职后档案不给怎么办 档案不小心拆了怎么办 退休职工档案年龄有涂改怎么办 养老金原始档案找不到怎么办退休 寄辞职信不接收怎么办 公司不给办离职怎么办 离职手续表填写错误怎么办 退货少退了个配件怎么办 小米8拖影严重怎么办 被兼职中介骗了怎么办 被兼职中介坑了怎么办 人在工厂宿舍死了怎么办 事业单位在编人员开除后社保怎么办 因违规无法进群怎么办 微信号违规进不了群怎么办 工作跨省调动社保怎么办 工作中看到别人违反规定应该怎么办 深户调令过期了怎么办 特岗教师满三年怎么办 特岗教师想辞职怎么办 入职一周想离职怎么办 原单位买断工龄后档案怎么办 北京国企辞职后户口怎么办 工作档案弄丢了怎么办 沈阳大集体职工工龄漏算怎么办 集体职工工龄漏算怎么办 cad打开字体是问号怎么办 cad中字体显示问号怎么办 代扣代缴个税申报逾期申报怎么办