气死我了,调了一个下午+两节课,各种大大小小的错误,各种调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. CPU总线

    总线(Bus)是计算机各种功能部件之间传送信息的公共通信干线,它是由导线组成的传输线束.按照计算机所传输的信息种类,计算机的总线可以划分为数据总线.地址总线和控制总线,分别用来传输数据.数据地址和控制 ...

  2. 以POST方式推送JSON数据,并接收返回的服务器消息

    private static string GetResult(string jsonString, string type) { string url = GetUrl(type); string ...

  3. 模板—treap

    #include<iostream> #include<cstdio> #include<cstdlib> #define INF 0x7fffffff using ...

  4. myeclipse工具常用的用法

    1.  自动提示:窗口->首选项->Java->编辑器->内容辅助->自动激活,在下面的“Java的自动激活触发器里面填上“.abcdefghijklmnopqrstuv ...

  5. POJ P2096 Collecting Bugs

    思路 分类讨论,不妨先设$DP[i][j]$表示已经发现$i$种子系统中有$n$种$bug$无非只有四种情况 发现的$bug$在旧的系统旧的分类,概率$p1$是$(i/s)*(j/n)$. 发现的$b ...

  6. ROS lesson 1

    ROS ROS官网 ROS 简介 ROS 是 Robot Operation System 的简写,并且 他诞生在2000年后,至今有10余年了,运行在 Linux(Ubuntu) 上 ROS 不是 ...

  7. 百练4103:踩方格(DFS)

    描述 有一个方格矩阵,矩阵边界在无穷远处.我们做如下假设:a.    每走一步时,只能从当前方格移动一格,走到某个相邻的方格上:b.    走过的格子立即塌陷无法再走第二次:c.    只能向北.东. ...

  8. 【Codeforces 484A】Bits

    [链接] 我是链接,点我呀:) [题意] 让你求出l~r当中二进制表示1的个数最多的数x [题解] 最多有64位 我们可以从l开始一直增大到r 怎么增大? 找到l的二进制表示当中0所在的位置 假设i这 ...

  9. Leetcode 92.反转链表

    92.反转链表 反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明:1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4->5->NULL ...

  10. [luoguP2896] [USACO08FEB]一起吃饭Eating Together(DP)

    传送门 由于 Di 只有 3 种情况,那么就很简单了 f[i][j][0] 表示前 i 个,且第 i 个变成 j 的 递增序列最小修改次数 f[i][j][1] 表示前 i 个,且第 i 个变成 j ...