[模板]平衡树splay
气死我了,调了一个下午+两节课,各种大大小小的错误,各种调QAQ,最后总之是调出来了.
其实就是一个双旋操作,然后其他就是左儿子<当前节点<右儿子,剩下就是细节了.
题干:
题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入xxx数 删除xxx数(若有多个相同的数,因只删除一个) 查询xxx数的排名(排名定义为比当前数小的数的个数+1+1+1。若有多个相同的数,因输出最小的排名) 查询排名为xxx的数 求xxx的前驱(前驱定义为小于xxx,且最大的数) 求xxx的后继(后继定义为大于xxx,且最小的数) 输入输出格式 输入格式: 第一行为nnn,表示操作的个数,下面nnn行每行有两个数optoptopt和xxx,optoptopt表示操作的序号( 1≤opt≤6 1 \leq opt \leq 6 1≤opt≤6 ) 输出格式: 对于操作3,4,5,63,4,5,63,4,5,6每行输出一个数,表示对应答案 输入输出样例 输入样例#1: 复制 10 1 106465 4 1 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598 输出样例#1: 复制 106465 84185 492737
代码:
#include<iostream> #include<cstdio> #include<cmath> #include<queue> #include<algorithm> #include<vector> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) #define pr pair<int,int> #define mp make_pair const int INF = 2147480000; const double eps = 1e-8; typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } struct node { int v,fa,ch[3],sum,recy; }e[500005]; int n,points,N; #define root e[0].ch[1] void update(int x) { e[x].sum = e[e[x].ch[0]].sum + e[e[x].ch[1]].sum + e[x].recy; } int iden(int x) { return e[e[x].fa].ch[0] == x ? 0 : 1; } void connect(int x,int f,int son) { e[x].fa = f; e[f].ch[son] = x; } void rotate(int x) { int y = e[x].fa; int mroot = e[y].fa; int mrootson = iden(y); int yson = iden(x); int b = e[x].ch[yson ^ 1]; connect(b,y,yson); connect(y,x,yson ^ 1); connect(x,mroot,mrootson); update(y); update(x); } void splay(int at,int to) { to = e[to].fa; while(e[at].fa != to) { int up = e[at].fa; if(e[up].fa == to) rotate(at); else if(iden(up) == iden(at)) { rotate(up); rotate(at); } else { rotate(at); rotate(at); } } } int crepoint(int v,int fa) { n++; e[n].v = v; e[n].fa = fa; // cout<<v<<" "<<fa<<endl; e[n].sum = e[n].recy = 1; return n; } void destroy(int x) { e[x].v = e[x].ch[0] = e[x].ch[1] = e[x].sum = e[x].fa = e[x].recy = 0; if(x == n) n--; while(e[n].v == 0 && e[n].sum == 0 && n > 0) n--; } int find(int v) { int now = root; while(true) { if(e[now].v == v) { splay(now,root); return now; } int nxt = v < e[now].v ? 0 : 1; if(!e[now].ch[nxt]) return 0; now = e[now].ch[nxt]; } } int build(int v) { points++; // cout<<v<<endl; if(n == 0) { root = 1; crepoint(v,0); } else { int now = root; while(true) { // cout<<now<<endl; e[now].sum++; if(v == e[now].v) { e[now].recy++; return now; } int nxt = v < e[now].v ? 0 : 1; if(!e[now].ch[nxt]) { crepoint(v,now); e[now].ch[nxt] = n; return n; } now = e[now].ch[nxt]; } } return 0; } void push(int v) { int add = build(v); if( rand() % 20 == 1 ) splay(add,root); } void pop(int v) { int deal = find(v); if(!deal) return; points--; if(e[deal].recy > 1) { e[deal].recy--; e[deal].sum--; return; } if(!e[deal].ch[0]) { root = e[deal].ch[1]; e[root].fa = 0; } else { int lef = e[deal].ch[0]; while(e[lef].ch[1]) lef = e[lef].ch[1]; splay(lef,e[deal].ch[0]); int rig = e[deal].ch[1]; connect(rig,lef,1);connect(lef,0,1); update(lef); } destroy(deal); } int Rank(int v) { int ans = 0,now = root; // cout<<v<<endl; while(true) { if(e[now].v == v) return ans + e[e[now].ch[0]].sum + 1; if(now == 0) return 0; if(v < e[now].v) now = e[now].ch[0]; else { ans = ans + e[e[now].ch[0]].sum + e[now].recy; now = e[now].ch[1]; } } //if(now) splay(now,root); return 0; } int atRank(int x) { if(x > points) return -INF; int now = root; // cout<<root<<endl; while(true) { // cout<<now<<endl; int minused = e[now].sum - e[e[now].ch[1]].sum; if(x > e[e[now].ch[0]].sum && x <= minused) break; if(x < minused) now = e[now].ch[0]; else { x = x - minused; now = e[now].ch[1]; } } //splay(now,root); return e[now].v; } int upper(int v) { int now = root; int result = INF; while(now) { if(e[now].v > v && e[now].v < result) result = e[now].v; if(v < e[now].v) now = e[now].ch[0]; else now = e[now].ch[1]; } return result; } int lower(int v) { int now = root; int result = -INF; while(now) { // cout<<now<<endl; if(e[now].v < v && e[now].v > result) result = e[now].v; if(v > e[now].v) now = e[now].ch[1]; else now = e[now].ch[0]; } return result; } void Szcheck( int pos ){ if( e[pos].ch[0] ) Szcheck(e[pos].ch[0]); if( e[pos].ch[1] ) Szcheck(e[pos].ch[1]); if( e[e[pos].ch[0]].sum + 1 + e[e[pos].ch[1]].sum != e[pos].sum ){ cout << "Size Error At Pos" << pos << endl; } } void gg() { cout<<n<<endl; duke(i,1,n) { printf("%d ",e[i].v); } puts(""); } int main() { // freopen("3369.in","r",stdin); read(N); duke(i,1,N) { int opt,value; // cout<<endl<<i<<endl; read(opt);read(value); // if(opt != 1 && opt != 2) // cout<<opt<<" "<<value<<endl; switch(opt) { case 1 : push(value);break; case 2 : pop(value);break; case 3 : cout<<Rank(value)<<endl;break; case 4 : {cout<<atRank(value)<<endl;}break; case 5 : cout<<lower(value)<<endl;break; case 6 : cout<<upper(value)<<endl;break; case 7 : gg(); } //Szcheck(root); // cout<<i<<endl; } return 0; } /* 10 1 106465 1 317721 1 460929 1 644985 1 84185 1 89851 6 81968 1 492737 5 493598 4 1 */
代码有点长...
只想找一个不会伤害我的人