3224: Tyvj 1728 普通平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 16841 Solved: 7319
[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
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
84185
492737
HINT
1.n的数据范围:n<=100000
2.每个数的数据范围:[-2e9,2e9]
Source
很裸的平衡树Treep,Splay都能写
#include <bits/stdc++.h> using namespace std; char buf[1<<15],*fs,*ft; inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;} inline int read(){ int x=0,f=1; char ch=getc(); while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getc();} while(isdigit(ch)) {x=x*10+ch-'0'; ch=getc();} return x*f; } void put(int x){ if(x==0){ putchar('0'); putchar(' '); return; } if(x<0){ putchar('-'); x=-x; } int num=0;char ch[16]; while(x) ch[++num]=x%10+'0',x/=10; while(num) putchar(ch[num--]); putchar(' '); } const int MAXN=1e6+10; namespace zhangenming{ struct node{ int weight,sum,have,v;//weight表示节点的含有个数,sum表示所有子节点的和,have表示优先级,v表示节点的值 int leftt,rightt; }T[MAXN]; int n,tol=0,ans=0,root=0; inline void update(int root){ T[root].sum=T[T[root].leftt].sum+T[T[root].rightt].sum+T[root].weight; } inline void left_rote(int &now){ int tmp=T[now].rightt; T[tmp].sum=T[now].sum; T[now].rightt=T[tmp].leftt; T[tmp].leftt=now; update(now);now=tmp; } inline void right_rote(int &now){ int tmp=T[now].leftt; T[tmp].sum=T[now].sum; T[now].leftt=T[tmp].rightt; T[tmp].rightt=now; update(now);now=tmp; } inline void insert(int x,int &root){ if(root==0){ tol++;root=tol;T[root].v=x; T[root].weight=T[root].sum=1; T[root].have=rand();return ; } T[root].sum++; if(T[root].v==x) {T[root].weight++;} else{ if(x<T[root].v){ insert(x,T[root].leftt); if(T[T[root].leftt].have>T[root].have) right_rote(root); } else{ insert(x,T[root].rightt); if(T[T[root].rightt].have>T[root].have) left_rote(root); } } } inline void delte(int x,int &root){ if(root==0) return ; if(x==T[root].v){ if(T[root].weight>1){ T[root].weight--;T[root].sum--;return ; } if(T[root].leftt*T[root].rightt==0){ root=T[root].leftt+T[root].rightt; } else{ if(T[T[root].leftt].have<T[T[root].rightt].have){ right_rote(root);delte(x,root); } else{ left_rote(root);delte(x,root); } } } else{ if(T[root].v>x) {T[root].sum--;delte(x,T[root].leftt);} else {T[root].sum--;delte(x,T[root].rightt);} } } inline int getrank(int x,int root){ if(root==0) return 0; if(T[root].v>x) return getrank(x,T[root].leftt); else{ if(T[root].v<x) return T[T[root].leftt].sum+T[root].weight+getrank(x,T[root].rightt); else return T[T[root].leftt].sum+1; } } inline int getnum(int x,int root){ if(root==0) return 0; if(x>T[root].weight+T[T[root].leftt].sum){ return getnum(x-T[root].weight-T[T[root].leftt].sum,T[root].rightt); } else{ if(x>T[T[root].leftt].sum){ return T[root].v; } else{ return getnum(x,T[root].leftt); } } } inline void getpre(int x,int root){ if(root==0) return; if(T[root].v<x){ ans=T[root].v; getpre(x,T[root].rightt); } else getpre(x,T[root].leftt); } inline void getnext(int x,int root){ if(root==0) return; if(T[root].v>x){ ans=T[root].v; getnext(x,T[root].leftt); } else getnext(x,T[root].rightt); } void init(){ n=read(); for(int i=1;i<=n;i++){ int id=read(); int xx=read(); if(id==1) insert(xx,root); if(id==2) delte(xx,root); if(id==3) put(getrank(xx,root)); if(id==4) put(getnum(xx,root)); if(id==5) {getpre(xx,root);put(ans);} if(id==6) {getnext(xx,root);put(ans);} } } } int main(){ //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); using namespace zhangenming; init(); return 0; }