• bzoj3224 Tyvj 1728 普通平衡树(名次树+处理相同)


    3224: Tyvj 1728 普通平衡树

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 5354  Solved: 2196
    [Submit][Status][Discuss]

    Description

    您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
    1. 插入x数
    2. 删除x数(若有多个相同的数,因只删除一个)
    3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
    4. 查询排名为x的数
    5. 求x的前驱(前驱定义为小于x,且最大的数)
    6. 求x的后继(后继定义为大于x,且最小的数)

    Input

    第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)

    Output

    对于操作3,4,5,6每行输出一个数,表示对应答案

    Sample Input

    10
    1 106465
    4 1
    1 317721
    1 460929
    1 644985
    1 84185
    1 89851
    6 81968
    1 492737
    5 493598

    Sample Output

    106465
    84185
    492737

    HINT

    1.n的数据范围:n<=100000
    2.每个数的数据范围:[-1e7,1e7]

    【思路】

        Rank tree

        Treap实现名次树。需要多维护s,w域分别表示节点数目与相同键值的数目,相应修改maintain,remove和rank操作。

        需要注意的是不能单单在insert的时候安排相同结点放在右子,因为有可能结点通过旋转转上来,这就违反了我们的初衷。

    【代码】

     1 #include<cstdio>
     2 #include<ctime>
     3 #include<cstring>
     4 #include<cstdlib>
     5 #include<iostream>
     6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     7 using namespace std;
     8 
     9 struct Node{
    10     Node* ch[2];
    11     int v,r,s,w;
    12     Node(int x):v(x) { ch[0]=ch[1]=NULL; s=w=1; r=rand(); }
    13     void maintain() {
    14         s=w;                                    //change
    15         if(ch[0]!=NULL) s+=ch[0]->s;
    16         if(ch[1]!=NULL) s+=ch[1]->s;
    17     }
    18     int cmp(int x) const {
    19         if(x==v) return -1;  return x<v?0:1; 
    20     }
    21 };
    22 void rotate(Node* &o,int d) {
    23     Node* k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o;
    24     o->maintain(); k->maintain(); o=k;
    25 }
    26 //不能只是把大于等于x的放在右子树 有可能旋上来
    27 void insert(Node* &o,int x) {
    28     if(o==NULL) o=new Node(x);
    29     else {
    30         int d=o->cmp(x);
    31         if(d==-1) { o->w++; o->maintain(); return;    }    //相同键值的个数 
    32         insert(o->ch[d],x);
    33         if(o->ch[d]->r > o->r) rotate(o,d^1);
    34     }
    35     o->maintain();
    36 }
    37 void remove(Node* &o,int x){
    38     if(o==NULL) return ;
    39     int d=o->cmp(x);
    40     if(d==-1) {
    41         Node* u=o;
    42         if(o->w>1) { o->w--; o->maintain(); return ; }  //change2
    43         if(o->ch[0]!=NULL && o->ch[1]!=NULL) {
    44             int d2=o->ch[0]->r > o->ch[1]->r? 1:0;
    45             rotate(o,d2); remove(o->ch[d2],x);
    46         }
    47         else {
    48             if(o->ch[0]!=NULL) o=o->ch[0]; else o=o->ch[1];
    49             delete u;
    50         }
    51     }
    52     else remove(o->ch[d],x);
    53     if(o!=NULL) o->maintain();
    54 }
    55 int kth(Node* o,int k) {
    56     if(o==NULL || k<=0 || k>o->s) return 0;
    57     int s=o->ch[0]==NULL? 0:o->ch[0]->s,w=o->w;
    58     if(s+1<=k && k<=s+w) return o->v;
    59     else if(k<=s) return kth(o->ch[0],k);
    60     else return kth(o->ch[1],k-s-w);
    61 }
    62 int rank(Node* o,int x) {
    63     if(o==NULL) return 0;
    64     int d=o->cmp(x),s=o->ch[0]==NULL?0:o->ch[0]->s;
    65     int f= d==1? s+o->w:0;
    66     if(d==-1) return s+1;
    67     else return rank(o->ch[d],x)+f;
    68 }
    69 void query1(Node* o,int x,int& ans) {
    70     if(o==NULL) return ;
    71     if(o->v<x) { ans=o->v; query1(o->ch[1],x,ans); }
    72     else query1(o->ch[0],x,ans);
    73 }
    74 void query2(Node* o,int x,int& ans) {
    75     if(o==NULL) return ;
    76     if(o->v>x) { ans=o->v; query2(o->ch[0],x,ans); }
    77     else query2(o->ch[1],x,ans);
    78 }
    79 int n,opt,x,ans;
    80 Node* root=NULL;
    81 
    82 int main() {
    83     //srand(time(0));    //bzoj上不要用 否则RE 
    84     scanf("%d",&n);
    85     FOR(i,1,n) {
    86         scanf("%d%d",&opt,&x);
    87         switch(opt) {
    88             case 1:  insert(root,x);  break;
    89             case 2:  remove(root,x);  break;
    90             case 3:  printf("%d
    ",rank(root,x));   break;
    91             case 4:  printf("%d
    ",kth(root,x));    break;
    92             case 5:  ans=0;  query1(root,x,ans); printf("%d
    ",ans);   break;
    93             case 6:  ans=0;  query2(root,x,ans); printf("%d
    ",ans);   break;
    94         }
    95     }
    96     return 0;
    97 }
  • 相关阅读:
    20200929-git地址
    20200917-1 每周例行报告
    20200917-2 词频统计
    20200917-3 白名单
    20200910-1 每周例行报告
    20200910-2 博客作业
    20190919-6 四则运算试题生成,结对
    20190919-3 效能分析
    20190919-2 功能测试
    20190912-1 每周例行报告
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5019177.html
Copyright © 2020-2023  润新知