• BZOJ 3224 Tyvj 1728 普通平衡树


    3224: Tyvj 1728 普通平衡树

    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.每个数的数据范围:[-2e9,2e9]

      第一次这么仔细的打平衡树。但方法绝不仅仅止于此。
      因为是裸题,所以可以用:
    • 树状数组fenwick
    • 线段树(因为树状数组可以)
    • 近乎于暴力的vector
    • 平衡树家族
      • 红黑树rbt
      • 节点大小平衡树sbt
      • splay
      • 替罪羊树sgt
      • treap  
      1 /**************************************************************
      2     Problem: 3224
      3     User: Doggu
      4     Language: C++
      5     Result: Accepted
      6     Time:304 ms
      7     Memory:3164 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio>
     11 #include <cmath>
     12 #include <algorithm>
     13 #define sm(a,b,c) {if(c==0) a=std::max(a,b);else a=std::min(a,b);}
     14 template<class T> inline void readin(T &res) {
     15     static char ch;T flag=1;
     16     while((ch=getchar())<48||ch>57)if(ch=='-')flag=-1;
     17     res=ch-48;
     18     while((ch=getchar())>=48&&ch<=57)res=(res<<1)+(res<<3)+ch-'0';
     19     res*=flag;
     20 }
     21 const int N = 100005;
     22 const int INF = 0x3f3f3f3f;
     23 struct Node {
     24     int key, w, size, rd;
     25     Node *ch[2];
     26     int cmp(int x) {
     27         if(x==key) return -1;
     28         return x>key;
     29     }
     30     void maintain() {size = ch[0]->size + ch[1]->size + w;}
     31 }pool[N], *tail=pool, *root=pool, *null=pool;
     32 int rand() {
     33     static int seed=1000007;
     34     return seed=(int)seed*48271LL%2147483647;
     35 }
     36 Node* newnode() {
     37     Node *nd = tail++;
     38     nd->rd=rand();nd->ch[0]=nd->ch[1]=null;
     39     return nd;
     40 }
     41 void rotate(Node *&nd,int d) {//d=0 right(1) to left(0) d=1 left(0) to right(1)
     42     Node *k=nd->ch[d^1];nd->ch[d^1]=k->ch[d];k->ch[d]=nd;
     43     nd->maintain();k->maintain();nd=k;
     44 }
     45 void insert(Node *&nd,int x) {
     46     if(nd==null) nd=newnode(),nd->key=x,nd->w=1;
     47     else {
     48         int d=nd->cmp(x);
     49         if(d==-1) nd->w++;
     50         else {
     51             insert(nd->ch[d],x);
     52             if(nd->ch[d]->rd>nd->rd) rotate(nd,d^1);
     53         }
     54     }
     55     nd->maintain();
     56 }
     57 void del(Node *&nd,int x) {
     58     if(nd==null) return ;
     59     int d=nd->cmp(x);
     60     if(d==-1) {
     61         if(nd->w>1) nd->w--;
     62         else if(nd->ch[0] == null) nd=nd->ch[1];
     63         else if(nd->ch[1] == null) nd=nd->ch[0];
     64         else if(nd->ch[1]>nd->ch[0]) rotate(nd,0),del(nd->ch[0],x);
     65         else rotate(nd,1),del(nd->ch[1],x);
     66     } else del(nd->ch[d],x);
     67     nd->maintain();
     68 }
     69 int find(Node *nd,int x) {
     70     while(nd!=null) {
     71         int d=nd->cmp(x);
     72         if(d==-1) return 1;
     73         nd=nd->ch[d];
     74     }
     75     return 0;
     76 }
     77 int rnk(Node *nd,int x) {
     78     int d=nd->cmp(x);
     79     if(d==-1) return nd->ch[0]->size+1;
     80     if(d==0) return rnk(nd->ch[0],x);
     81     return nd->ch[0]->size+nd->w+rnk(nd->ch[1],x);
     82 }
     83 int kth(Node *nd,int x) {
     84     if(x<=nd->ch[0]->size) return kth(nd->ch[0],x);
     85     if(nd->ch[0]->size<x && x<=nd->ch[0]->size+nd->w) return nd->key;
     86     return kth(nd->ch[1],x-nd->ch[0]->size-nd->w);
     87 }
     88 int temp;
     89 void near(Node *nd,int x,int delta) {
     90     if(nd==null) return ;
     91     int d=nd->cmp(x);
     92     if(d==!delta) sm(temp,nd->key,delta);
     93     if(d==-1) near(nd->ch[delta],x,delta);
     94     else near(nd->ch[d],x,delta);
     95 }
     96  
     97 /*void print(Node *nd) {
     98     if(nd==null) return ;
     99     print(nd->ch[0]);
    100     for( int i = 1; i <= nd->w; i++ ) printf("%d ",nd->key);
    101     print(nd->ch[1]);
    102 }*/
    103  
    104 int main() {
    105     //freopen("in.txt","r",stdin);
    106     //freopen("out.txt","w",stdout);
    107     null=newnode();
    108     int n, opt, x;
    109     readin(n);
    110     for( int i = 1; i <= n; i++ ) {
    111         readin(opt);readin(x);
    112         if(opt==1) {//插入x数
    113             insert(root,x);
    114         }else if(opt==2) {//删除x数(若有多个相同的数,因只删除一个)
    115             del(root,x);
    116         }else if(opt==3) {//查询x数的排名(若有多个相同的数,因输出最小的排名)
    117             if(find(root,x)) printf("%d
    ",rnk(root,x));
    118         }else if(opt==4) {//查询排名为x的数
    119             if(root->size>=x) printf("%d
    ",kth(root,x));
    120         }else if(opt==5) {//求x的前驱
    121             temp=-INF;near(root,x,0);if(temp!=-INF)printf("%d
    ",temp);
    122         }else if(opt==6) {//求x的后继 
    123             temp=INF;near(root,x,1);if(temp!=INF)printf("%d
    ",temp);
    124         }
    125         //printf("SEQ:");print(root);putchar('
    ');
    126     }
    127     return 0;
    128 }
    129 
    TREAP
  • 相关阅读:
    协成
    进程与线程-多线程
    进程与线程2
    进程与线程
    socket编程
    常用模块二(hashlib、configparser、logging)
    异常处理
    python之路——面向对象进阶
    封装
    初识——面向对象
  • 原文地址:https://www.cnblogs.com/Doggu/p/bzoj3224.html
Copyright © 2020-2023  润新知