气死我了,调了一个下午+两节课,各种大大小小的错误,各种调QAQ,最后总之是调出来了.

其实就是一个双旋操作,然后其他就是左儿子<当前节点<右儿子,剩下就是细节了.

题干:

题目描述

您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:

    插入xxx数
删除xxx数(若有多个相同的数,因只删除一个)
查询xxx数的排名(排名定义为比当前数小的数的个数+++。若有多个相同的数,因输出最小的排名)
查询排名为xxx的数
求xxx的前驱(前驱定义为小于xxx,且最大的数)
求xxx的后继(后继定义为大于xxx,且最小的数) 输入输出格式
输入格式: 第一行为nnn,表示操作的个数,下面nnn行每行有两个数optoptopt和xxx,optoptopt表示操作的序号( ≤opt≤ \leq opt \leq ≤opt≤ ) 输出格式: 对于操作3,,,,,,,,,6每行输出一个数,表示对应答案 输入输出样例
输入样例#: 复制 输出样例#: 复制

代码:

#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 = ;
const double eps = 1e-;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
char c;
bool op = ;
while(c = getchar(), c < '' || c > '')
if(c == '-') op = ;
x = c - '';
while(c = getchar(), c >= '' && c <= '')
x = x * + c - '';
if(op) x = -x;
}
template <class T>
void write(T x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar('' + x % );
}
struct node
{
int v,fa,ch[],sum,recy;
}e[];
int n,points,N;
#define root e[0].ch[1]
void update(int x)
{
e[x].sum = e[e[x].ch[]].sum + e[e[x].ch[]].sum + e[x].recy;
}
int iden(int x)
{
return e[e[x].fa].ch[] == x ? : ;
}
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 ^ ];
connect(b,y,yson);
connect(y,x,yson ^ );
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 = ;
return n;
}
void destroy(int x)
{
e[x].v = e[x].ch[] = e[x].ch[] = e[x].sum = e[x].fa = e[x].recy = ;
if(x == n)
n--;
while(e[n].v == && e[n].sum == && n > )
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 ? : ;
if(!e[now].ch[nxt]) return ;
now = e[now].ch[nxt];
}
}
int build(int v)
{
points++;
// cout<<v<<endl;
if(n == )
{
root = ;
crepoint(v,);
}
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 ? : ;
if(!e[now].ch[nxt])
{
crepoint(v,now);
e[now].ch[nxt] = n;
return n;
}
now = e[now].ch[nxt];
}
}
return ;
}
void push(int v)
{
int add = build(v);
if( rand() % == )
splay(add,root);
}
void pop(int v)
{
int deal = find(v);
if(!deal) return;
points--;
if(e[deal].recy > )
{
e[deal].recy--;
e[deal].sum--;
return;
}
if(!e[deal].ch[])
{
root = e[deal].ch[];
e[root].fa = ;
}
else
{
int lef = e[deal].ch[];
while(e[lef].ch[]) lef = e[lef].ch[];
splay(lef,e[deal].ch[]);
int rig = e[deal].ch[];
connect(rig,lef,);connect(lef,,);
update(lef);
}
destroy(deal);
}
int Rank(int v)
{
int ans = ,now = root;
// cout<<v<<endl;
while(true)
{
if(e[now].v == v)
return ans + e[e[now].ch[]].sum + ;
if(now == ) return ;
if(v < e[now].v) now = e[now].ch[];
else
{
ans = ans + e[e[now].ch[]].sum + e[now].recy;
now = e[now].ch[];
}
}
//if(now) splay(now,root);
return ;
}
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[]].sum;
if(x > e[e[now].ch[]].sum && x <= minused) break;
if(x < minused) now = e[now].ch[];
else
{
x = x - minused;
now = e[now].ch[];
}
}
//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[];
else
now = e[now].ch[];
}
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[];
else
now = e[now].ch[];
}
return result;
}
void Szcheck( int pos ){
if( e[pos].ch[] ) Szcheck(e[pos].ch[]);
if( e[pos].ch[] ) Szcheck(e[pos].ch[]);
if( e[e[pos].ch[]].sum + + e[e[pos].ch[]].sum != e[pos].sum ){
cout << "Size Error At Pos" << pos << endl;
}
}
void gg()
{
cout<<n<<endl;
duke(i,,n)
{
printf("%d ",e[i].v);
}
puts("");
}
int main()
{
// freopen("3369.in","r",stdin);
read(N);
duke(i,,N)
{
int opt,value;
// cout<<endl<<i<<endl;
read(opt);read(value);
// if(opt != 1 && opt != 2)
// cout<<opt<<" "<<value<<endl;
switch(opt)
{
case : push(value);break;
case : pop(value);break;
case : cout<<Rank(value)<<endl;break;
case : {cout<<atRank(value)<<endl;}break;
case : cout<<lower(value)<<endl;break;
case : cout<<upper(value)<<endl;break;
case : gg();
}
//Szcheck(root);
// cout<<i<<endl;
}
return ;
}
/*
10
1 106465
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
4 1
*/

代码有点长...

[模板]平衡树splay的更多相关文章

  1. [模板] 平衡树: Splay, 非旋Treap, 替罪羊树

    简介 二叉搜索树, 可以维护一个集合/序列, 同时维护节点的 \(size\), 因此可以支持 insert(v), delete(v), kth(p,k), rank(v)等操作. 另外, prev ...

  2. 【阶梯报告】洛谷P3391【模板】文艺平衡树 splay

    [阶梯报告]洛谷P3391[模板]文艺平衡树 splay 题目链接在这里[链接](https://www.luogu.org/problemnew/show/P3391)最近在学习splay,终于做对 ...

  3. luoguP3391[模板]文艺平衡树(Splay) 题解

    链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ...

  4. 平衡树模板【splay的实现】

    [平衡树splay实现] 无注释代码 #include<bits/stdc++.h> using namespace std; typedef long long LL; ,MAXN=1e ...

  5. 【BZOJ3224】Tyvj 1728 普通平衡树 Splay

    Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数 ...

  6. BZOJ3224/洛谷P3391 - 普通平衡树(Splay)

    BZOJ链接 洛谷链接 题意简述 模板题啦~ 代码 //普通平衡树(Splay) #include <cstdio> int const N=1e5+10; int rt,ndCnt; i ...

  7. 平衡树——splay 一

    splay 一种平衡树,同时也是二叉排序树,与treap不同,它不需要维护堆的性质,它由Daniel Sleator和Robert Tarjan(没错,tarjan,又是他)创造,伸展树是一种自调整二 ...

  8. hiho #1329 : 平衡树·Splay

    #1329 : 平衡树·Splay 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. ...

  9. Hihocoder 1329 平衡树·Splay(平衡树)

    Hihocoder 1329 平衡树·Splay(平衡树) Description 小Ho:小Hi,上一次你跟我讲了Treap,我也实现了.但是我遇到了一个关键的问题. 小Hi:怎么了? 小Ho:小H ...

随机推荐

  1. Redis系列(十一)--阿里云开发规范

    本文主要介绍阿里云Redis的开发规范,主要从以下几个方面说明: 1.键值设计 2.命令使用 3.客户端使用 4.相关工具 一.键值设计 1.key name设计 1).[建议]:可读性和可管理性 以 ...

  2. Spring事物不回滚

    今天发现个自己的bug,仔细排查后,发现根本原因我在service方法中抛出的异常被控制层的方法捕获了,所以后台页面也只是出现个错误提示,而数据却没有回滚. 解决方式:对自己抛出的异常使用try ca ...

  3. cc.Node—Action

    1: Action类是动作命令,我们创建Action,然后节点运行action就能够执行Action的动作; 2: Action分为两类: (1) 瞬时就完成的ActionInstant, (2) 要 ...

  4. git 的 基础操作及使用

    /* git svn版本控制器 */ /*git把文件对应的储存空间分为三个区: 1.工作区 2.缓存区 3.历史区 直接操作文件,不做add时,咱们是在工作区做的修改 右键 git bash her ...

  5. 洛谷——P1475 控制公司 Controlling Companies

    P1475 控制公司 Controlling Companies 题目描述 有些公司是其他公司的部分拥有者,因为他们获得了其他公司发行的股票的一部分.(此处略去一句废话)据说,如果至少满足了以下三个条 ...

  6. HTTP服务和APACHE2

    HTTP服务和APACHE2 知识点 请求报文响应报文 错误码 请求重定向 编译安装 实现https curl工具 1. http协议 http协议版本 http/0.9, http/1.0, htt ...

  7. 【Codeforces 986B】Petr and Permutations

    [链接] 我是链接,点我呀:) [题意] 题意 [题解] n为奇数时3n和7n+1奇偶性不同 n为偶数时也是如此 然后交换任意一对数 逆序对的对数的奇偶性会发生改变一次 求出逆序对 对n讨论得出答案. ...

  8. CodeForcesGym 100753E Change of Scenery

    Change of Scenery Time Limit: 10000ms Memory Limit: 262144KB This problem will be judged on CodeForc ...

  9. [UOJ48] 核聚变反应强度

    QUQ 思路 求出a1的所有约数,与a1.ai放入同一数组: 求出gcd(a1,ai): 枚举约数,得出ans; 代码实现 #include<cmath> #include<cstd ...

  10. SVM学习(续)核函数 & 松弛变量和惩罚因子

    SVM的文章可以看:http://www.cnblogs.com/charlesblc/p/6193867.html 有写的最好的文章来自:http://www.blogjava.net/zhenan ...