您的位置:首页 > 其它

BZOJ 3224 Tyvj 1728 普通平衡树

2017-05-26 17:06 465 查看

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  

/**************************************************************
Problem: 3224
User: Doggu
Language: C++
Result: Accepted
Time:304 ms
Memory:3164 kb
****************************************************************/

#include <cstdio>
#include <cmath>
#include <algorithm>
#define sm(a,b,c) {if(c==0) a=std::max(a,b);else a=std::min(a,b);}
template<class T> inline void readin(T &res) {
static char ch;T flag=1;
while((ch=getchar())<48||ch>57)if(ch=='-')flag=-1;
res=ch-48;
while((ch=getchar())>=48&&ch<=57)res=(res<<1)+(res<<3)+ch-'0';
res*=flag;
}
const int N = 100005;
const int INF = 0x3f3f3f3f;
struct Node {
int key, w, size, rd;
Node *ch[2];
int cmp(int x) {
if(x==key) return -1;
return x>key;
}
void maintain() {size = ch[0]->size + ch[1]->size + w;}
}pool
, *tail=pool, *root=pool, *null=pool;
int rand() {
static int seed=1000007;
return seed=(int)seed*48271LL%2147483647;
}
Node* newnode() {
Node *nd = tail++;
nd->rd=rand();nd->ch[0]=nd->ch[1]=null;
return nd;
}
void rotate(Node *&nd,int d) {//d=0 right(1) to left(0) d=1 left(0) to right(1)
Node *k=nd->ch[d^1];nd->ch[d^1]=k->ch[d];k->ch[d]=nd;
nd->maintain();k->maintain();nd=k;
}
void insert(Node *&nd,int x) {
if(nd==null) nd=newnode(),nd->key=x,nd->w=1;
else {
int d=nd->cmp(x);
if(d==-1) nd->w++;
else {
insert(nd->ch[d],x);
if(nd->ch[d]->rd>nd->rd) rotate(nd,d^1);
}
}
nd->maintain();
}
void del(Node *&nd,int x) {
if(nd==null) return ;
int d=nd->cmp(x);
if(d==-1) {
if(nd->w>1) nd->w--;
else if(nd->ch[0] == null) nd=nd->ch[1];
else if(nd->ch[1] == null) nd=nd->ch[0];
else if(nd->ch[1]>nd->ch[0]) rotate(nd,0),del(nd->ch[0],x);
else rotate(nd,1),del(nd->ch[1],x);
} else del(nd->ch[d],x);
nd->maintain();
}
int find(Node *nd,int x) {
while(nd!=null) {
int d=nd->cmp(x);
if(d==-1) return 1;
nd=nd->ch[d];
}
return 0;
}
int rnk(Node *nd,int x) {
int d=nd->cmp(x);
if(d==-1) return nd->ch[0]->size+1;
if(d==0) return rnk(nd->ch[0],x);
return nd->ch[0]->size+nd->w+rnk(nd->ch[1],x);
}
int kth(Node *nd,int x) {
if(x<=nd->ch[0]->size) return kth(nd->ch[0],x);
if(nd->ch[0]->size<x && x<=nd->ch[0]->size+nd->w) return nd->key;
return kth(nd->ch[1],x-nd->ch[0]->size-nd->w);
}
int temp;
void near(Node *nd,int x,int delta) {
if(nd==null) return ;
int d=nd->cmp(x);
if(d==!delta) sm(temp,nd->key,delta);
if(d==-1) near(nd->ch[delta],x,delta);
else near(nd->ch[d],x,delta);
}

/*void print(Node *nd) {
if(nd==null) return ;
print(nd->ch[0]);
for( int i = 1; i <= nd->w; i++ ) printf("%d ",nd->key);
print(nd->ch[1]);
}*/

int main() {
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
null=newnode();
int n, opt, x;
readin(n);
for( int i = 1; i <= n; i++ ) {
readin(opt);readin(x);
if(opt==1) {//插入x数
insert(root,x);
}else if(opt==2) {//删除x数(若有多个相同的数,因只删除一个)
del(root,x);
}else if(opt==3) {//查询x数的排名(若有多个相同的数,因输出最小的排名)
if(find(root,x)) printf("%d\n",rnk(root,x));
}else if(opt==4) {//查询排名为x的数
if(root->size>=x) printf("%d\n",kth(root,x));
}else if(opt==5) {//求x的前驱
temp=-INF;near(root,x,0);if(temp!=-INF)printf("%d\n",temp);
}else if(opt==6) {//求x的后继
temp=INF;near(root,x,1);if(temp!=INF)printf("%d\n",temp);
}
//printf("SEQ:");print(root);putchar('\n');
}
return 0;
}


TREAP
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: