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\n",rnk(root,x));
118         }else if(opt==4) {//查询排名为x的数
119             if(root->size>=x) printf("%d\n",kth(root,x));
120         }else if(opt==5) {//求x的前驱
121             temp=-INF;near(root,x,0);if(temp!=-INF)printf("%d\n",temp);
122         }else if(opt==6) {//求x的后继 
123             temp=INF;near(root,x,1);if(temp!=INF)printf("%d\n",temp);
124         }
125         //printf("SEQ:");print(root);putchar('\n');
126     }
127     return 0;
128 }
129 
TREAP

 

posted @ 2017-05-26 17:06 Doggu 阅读(...) 评论(...) 编辑 收藏