红黑树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)
二次联通门 : luogu P3369 【模板】普通平衡树(Treap/SBT)
近几天闲来无事。。。就把各种平衡树都写了一下。。。
下面是红黑树(Red Black Tree)
喜闻乐见拿到了luogu,COGS的rank1
QAQ rank1没啦!!!被树状数组艹啦!!!
10.11 Updata 压了压行233333
#include <cstdio>
#include <iostream>
#define Max 100001
#define Red true
#define Black false
const int BUF = ; char Buf[BUF], *buf = Buf;
#define rg register
#define Inline __attri\
bute__( ( optimize( "-O2" ) ) )
Inline void read (int &n)
{
bool temp = false;
for (n = ; !isdigit (*buf); ++ buf) if (*buf == '-') temp = true;
for (; isdigit (*buf); n = n * + *buf - '', ++ buf);
if (temp) n = -n;
}
struct RD
{
int v, _s, _w; bool _c; RD *f, *c[];
Inline void Fill (const int &_v, const bool &__c, const int &z, rg RD *n)
{ v = _v, _c = __c, _s = _w = z, f = c[] = c[] = n; }
Inline void Up () { _s = c[]->_s + c[]->_s + _w; }
Inline void dn ()
{ for (RD *n = this; n->_s; n = n->f) -- n->_s; }
Inline int Get_Pos (const int &n) { return this->v == n ? - : n > v; }
};
class Red_Black_Tree
{
private : int _t; RD *Rt, *null, poor[Max], *Tail, *reuse[Max];
private : Inline RD *New (const int &v)
{
rg RD *n = null;
if (!_t) n = Tail ++; else n = reuse[-- _t];
n->Fill (v, Red, , null);
return n;
} Inline void R (RD *&n, const bool &_p)
{
rg RD *C = n->c[_p ^ ];
n->c[_p ^ ] = C->c[_p];
if (C->c[_p]->_s) C->c[_p]->f = n;
C->f = n->f; if (!n->f->_s) Rt = C;
else n->f->c[n->f->c[] != n] = C;
C->c[_p] = n; n->f = C; C->_s = n->_s; n->Up ();
} Inline void If (rg RD *&n)
{
for (; n->f->_c; )
{
RD *_F = n->f, *_g = _F->f;
bool _p = _F == _g->c[]; RD *_u = _g->c[_p];
if (_u->_c) _F->_c = _u->_c = Black, _g->_c = Red, n = _g;
else if (n == _F->c[_p]) R (n = _F, _p ^ );
else _g->_c = Red, _F->_c = Black, R (_g, _p);
}
Rt->_c = Black;
} Inline RD *Find (RD *n, int v)
{
for (; n->_s && n->v != v; n = n->c[n->v < v]);
return n;
} Inline void Df (rg RD *&n)
{
for (; n != Rt && n->_c == Black; )
{
rg bool _p = n == n->f->c[];
RD *_F = n->f, *_u = _F->c[_p];
if (_u->_c == Red)
_u->_c = Black, _F->_c = Red, R (n->f, _p ^ ), _u = _F->c[_p];
else if (_u->c[]->_c == Black && _u->c[]->_c == Black)
_u->_c = Red, n = _F;
else
{
if (_u->c[_p]->_c == Black)
_u->c[_p ^ ]->_c = Black, _u->_c = Red, R (_u, _p), _u = _F->c[_p];
_u->_c = _F->_c, _u->c[_p]->_c = _F->_c = Black, R (_F, _p ^ );
break;
}
}
n->_c = Black;
} public : Red_Black_Tree ()
{
_t = , Tail = &poor[_t];
null = Tail ++, null->Fill (, Black, , NULL), Rt = null;
} Inline void Insert (const int &v)
{
rg RD *n = Rt, *_F = null;
rg int _p;
for (; n->_s; n = n->c[_p])
{
++ n->_s, _F = n, _p = n->Get_Pos (v);
if (_p == -) { ++ n->_w; return ; }
}
n = New (v);
if (_F->_s) _F->c[v > _F->v] = n; else Rt = n;
n->f = _F; If (n);
} Inline void Delete (const int &v)
{
rg RD *_r = Find (Rt, v);
if (!_r->_s) return ;
if (_r->_w > ) { -- _r->_w, _r->dn (); return ; }
rg RD *_F = _r, *n = null;
if (_r->c[]->_s && _r->c[]->_s)
for (_F = _r->c[]; _F->c[]->_s; _F = _F->c[]);
n = _F->c[!_F->c[]->_s], n->f = _F->f;
if (!_F->f->_s) Rt = n;
else _F->f->c[_F->f->c[] == _F] = n;
if (_r != _F) _r->v = _F->v, _r->_w = _F->_w;
_F->f->dn ();
for (RD *p = _F->f; _F->_w > && p->_s && p != _r; p->_s -= _F->_w - , p = p->f);
if (_F->_c == Black) Df (n);
reuse[_t ++] = _F;
} Inline int Get_kth_number (rg int k)
{
rg int _r; rg RD *n = Rt;
for (; n->_s; )
{
_r = n->c[]->_s;
if (k <= _r) n = n->c[];
else if (_r + <= k && k <= _r + n->_w) break;
else k -= _r + n->_w, n = n->c[];
}
return n->v;
} Inline int Get_rank (const int &v)
{
rg int _r, cur = ; rg RD *n = Rt;
for (; n->_s; )
{
_r = n->c[]->_s;
if (n->v == v) break;
else if (n->v > v) n = n->c[];
else cur += _r + n->_w, n = n->c[];
}
return cur + _r + ;
} Inline int Find_Suffix (const int &v)
{
rg int _r = ;
for (RD *n = Rt; n->_s; )
if (n->v > v) _r = n->v, n = n->c[];
else n = n->c[];
return _r; } Inline int Find_Prefix (const int &v)
{
rg int _r = ;
for (RD *n = Rt; n->_s; )
if (n->v < v) _r = n->v, n = n->c[];
else n = n->c[];
return _r;
}
};
Red_Black_Tree Rbt;
void write_ (int n)
{ if (n > ) write_ (n / ); putchar (n % + ''); }
inline void write (int n)
{
if (n < ) putchar ('-'), n = -n;
write_ (n); putchar ('\n');
}
int Main ()
{
fread (buf, , BUF, stdin); int N; read (N);
for (int type, x; N --; )
{
read (type); read (x);
if (type == ) Rbt.Insert (x);
else if (type == ) Rbt.Delete (x);
else if (type == ) write (Rbt.Get_rank (x));
else if (type == ) write (Rbt.Get_kth_number (x));
else if (type == ) write (Rbt.Find_Prefix (x));
else write (Rbt.Find_Suffix (x));
}
return ;
}
int ZlycerQan = Main(); int main(int argc, char *argv[]){;}
#include <cstdio>
#include <iostream> #define Max 100001 #define Red true
#define Black false const int BUF = ;
char Buf[BUF], *buf = Buf; #define Inline __attri\
bute__( ( optimize( "-O2" ) ) )
Inline void read (int &now)
{
int temp = ;
for (now = ; !isdigit (*buf); ++ buf)
if (*buf == '-')
temp = ;
for (; isdigit (*buf); now = now * + *buf - '', ++ buf);
if (temp)
now = -now;
} struct R_D
{
int key, size, weigth;
bool color; R_D *father, *child[]; Inline void Fill (const int &__key, const bool &__color, const int &z, register R_D *now)
{
this->key = __key;
this->color = __color;
this->size = this->weigth = z; this->father = this->child[] = this->child[] = now;
} Inline void Up ()
{
this->size = this->child[]->size + this->child[]->size + this->weigth;
} Inline void Down ()
{
for (R_D *now = this; now->size; now = now->father)
now->size --;
} Inline int Get_Pos (const int &now) const
{
return this->key == now ? - : now > this->key;
}
}; class Red_Black_Tree
{ private : int Top; R_D *Root, *null;
R_D poor[Max], *Tail, *reuse[Max]; Inline R_D *New (const int &key)
{
register R_D *now = null;
if (!Top)
now = Tail ++;
else
now = reuse[-- Top];
now->Fill (key, Red, , null);
return now;
} Inline void Rotate (R_D *&now, const bool &pos)
{
register R_D *C = now->child[pos ^ ];
now->child[pos ^ ] = C->child[pos];
if (C->child[pos]->size)
C->child[pos]->father = now;
C->father = now->father;
if (!now->father->size)
Root = C;
else
now->father->child[now->father->child[] != now] = C;
C->child[pos] = now;
now->father = C;
C->size = now->size;
now->Up ();
} Inline void Insert_Fill (register R_D *&now)
{
for (; now->father->color; )
{
R_D *Father = now->father, *Grand = Father->father;
bool pos = Father == Grand->child[];
R_D *Uncle = Grand->child[pos];
if (Uncle->color)
{
Father->color = Uncle->color = Black;
Grand->color = Red;
now = Grand;
}
else if (now == Father->child[pos])
Rotate (now = Father, pos ^ );
else
{
Grand->color = Red;
Father->color = Black;
Rotate (Grand, pos);
}
}
Root->color = Black;
} Inline R_D *Find (R_D *now, int key)
{
for (; now->size && now->key != key; now = now->child[now->key < key]);
return now;
} Inline void Delete_Fill (register R_D *&now)
{
for (; now != Root && now->color == Black; )
{
register bool pos = now == now->father->child[];
R_D *Father = now->father, *Uncle = Father->child[pos];
if (Uncle->color == Red)
{
Uncle->color = Black;
Father->color = Red;
Rotate (now->father, pos ^ );
Uncle = Father->child[pos];
}
else if (Uncle->child[]->color == Black && Uncle->child[]->color == Black)
{
Uncle->color = Red;
now = Father;
}
else
{
if (Uncle->child[pos]->color == Black)
{
Uncle->child[pos ^ ]->color = Black;
Uncle->color = Red;
Rotate (Uncle, pos);
Uncle = Father->child[pos];
}
Uncle->color = Father->color;
Uncle->child[pos]->color = Father->color = Black;
Rotate (Father, pos ^ );
break;
}
}
now->color = Black;
} public : Red_Black_Tree ()
{
Top = ;
Tail = &poor[Top];
null = Tail ++;
null->Fill (, Black, , NULL);
Root = null;
} Inline void Insert (const int &key)
{
register R_D *now = Root, *Father = null;
register int pos;
for (; now->size; now = now->child[pos])
{
now->size ++;
Father = now;
pos = now->Get_Pos (key);
if (pos == -)
{
now->weigth ++;
return ;
}
}
now = New (key);
if (Father->size)
Father->child[key > Father->key] = now;
else
Root = now;
now->father = Father;
this->Insert_Fill (now);
} Inline void Delete (const int &key)
{
register R_D *res = Find (Root, key);
if (!res->size)
return ;
if (res->weigth > )
{
res->weigth --;
res->Down ();
return ;
}
register R_D *Father = res, *now = null; if (res->child[]->size && res->child[]->size)
for (Father = res->child[]; Father->child[]->size; Father = Father->child[]); now = Father->child[!Father->child[]->size];
now->father = Father->father;
if (!Father->father->size)
Root = now;
else
Father->father->child[Father->father->child[] == Father] = now; if (res != Father)
{
res->key = Father->key;
res->weigth = Father->weigth;
} Father->father->Down (); for (R_D *Fuck = Father->father; Father->weigth > && Fuck->size && Fuck != res; Fuck->size -= Father->weigth - , Fuck = Fuck->father); if (Father->color == Black)
Delete_Fill (now); reuse[Top ++] = Father;
} Inline int Get_kth_number (register int k)
{
register int res;
register R_D *now = Root; for (; now->size; )
{
res = now->child[]->size; if (k <= res)
now = now->child[];
else if (res + <= k && k <= res + now->weigth)
break;
else
{
k -= res + now->weigth;
now = now->child[];
}
}
return now->key;
} Inline int Get_rank (const int &key)
{
register int res, cur = ;
register R_D *now = Root; for (; now->size; )
{
res = now->child[]->size;
if (now->key == key)
break;
else if (now->key > key)
now = now->child[];
else
{
cur += res + now->weigth;
now = now->child[];
}
} return cur + res + ;
} Inline int Find_Suffix (const int &key)
{
register int res = ; for (R_D *now = Root; now->size; )
if (now->key > key)
{
res = now->key;
now = now->child[];
}
else
now = now->child[]; return res; } Inline int Find_Prefix (const int &key)
{
register int res = ; for (R_D *now = Root; now->size; )
if (now->key < key)
{
res = now->key;
now = now->child[];
}
else
now = now->child[];
return res;
}
}; Red_Black_Tree Rbt; void write_ (int now)
{
if (now > )
write_ (now / );
putchar (now % + '');
} inline void write (int now)
{
if (now < ) putchar ('-'), now = -now;
write_ (now);
putchar ('\n');
} int N; int Main ()
{
fread (buf, , BUF, stdin);
read (N); for (int type, x; N --; )
{
read (type);
read (x); switch (type)
{
case :
Rbt.Insert (x);
break;
case :
Rbt.Delete (x);
break;
case :
write (Rbt.Get_rank (x));
break;
case :
write (Rbt.Get_kth_number (x));
break;
case :
write (Rbt.Find_Prefix (x));
break;
case :
write (Rbt.Find_Suffix (x));
break;
}
} return ;
}
int ZlycerQan = Main();
int main(int argc, char *argv[]){;}
红黑树 ------ luogu P3369 【模板】普通平衡树(Treap/SBT)的更多相关文章
- luoguP3369[模板]普通平衡树(Treap/SBT) 题解
链接一下题目:luoguP3369[模板]普通平衡树(Treap/SBT) 平衡树解析 #include<iostream> #include<cstdlib> #includ ...
- 【模板】平衡树——Treap和Splay
二叉搜索树($BST$):一棵带权二叉树,满足左子树的权值均小于根节点的权值,右子树的权值均大于根节点的权值.且左右子树也分别是二叉搜索树.(如下) $BST$的作用:维护一个有序数列,支持插入$x$ ...
- 二叉树、平衡二叉树、红黑树、B树、B+树与B*树
转: 二叉树.平衡二叉树.红黑树.B树.B+树与B*树 一.二叉树 1️⃣二叉查找树的特点就是左子树的节点值比父亲节点小,而右子树的节点值比父亲节点大,如图: 基于二叉查找树的这种特点,在查找某个节点 ...
- 树:BST、AVL、红黑树、B树、B+树
我们这个专题介绍的动态查找树主要有: 二叉查找树(BST),平衡二叉查找树(AVL),红黑树(RBT),B~/B+树(B-tree).这四种树都具备下面几个优势: (1) 都是动态结构.在删除,插入操 ...
- Java集合详解6:TreeMap和红黑树
Java集合详解6:TreeMap和红黑树 初识TreeMap 之前的文章讲解了两种Map,分别是HashMap与LinkedHashMap,它们保证了以O(1)的时间复杂度进行增.删.改.查,从存储 ...
- 二叉查找树、平衡二叉树、红黑树、B-/B+树性能对比
转载:https://blog.csdn.net/z702143700/article/details/49079107 前言:BST.AVL.RBT.B-tree都是动态结构,查找时间基本都在O(l ...
- map,set的底层实现:红黑树[多图,手机慎入]
最近天下有一种颇不太平的感觉,各地的乱刀砍人,到处是贪官服法.京东准备上市了,阿里最近也提交申请了,猎豹也逆袭了,据说猎豹移动在国际市场上表现甚是抢眼.只有屌丝还在写着代码.花开花又谢,花谢花又开,为 ...
- [luogu P3369]【模板】普通平衡树(Treap/SBT)
[luogu P3369][模板]普通平衡树(Treap/SBT) 题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除x数(若有多个相同的数,因只删 ...
- 数组splay ------ luogu P3369 【模板】普通平衡树(Treap/SBT)
二次联通门 : luogu P3369 [模板]普通平衡树(Treap/SBT) #include <cstdio> #define Max 100005 #define Inline _ ...
随机推荐
- PMM--简介与部署
一.PMM架构 Percona Monitoring and Management是percona一款开源的用于管理和监控MySQL 和MongoDB性能的开源平台,通过PMM客户端收集到的DB监控数 ...
- JavaNetty
Netty的简单使用: import io.netty.bootstrap.Bootstrap; import io.netty.buffer.Unpooled; import io.netty.ch ...
- c#连接Access数据库及增删改查作
access:版本2003(后缀.mdb,新版access可另存为2003兼容版) using: using System;using System.Data;using System.Windows ...
- .net语音播放,自定义播报文字
// using System.Speech.Synthesis; SpeechSynthesizer synth = new SpeechSynthesizer(); // Configure th ...
- 转 C# 使用openssl
//先用大整数来生成一个1024bit的密钥对 RSA rsa = new RSA(); BigNumber number = OpenSSL.Core.Random.Next(10, 10, 1); ...
- java第四次面试总结
该公司没有笔试,直接就进行了面试,然后我就拿着我的简历瑟瑟发抖...... 1.因为是看简历来面试,所以面试官从我的项目下手,而我的项目都是后端的东西,虽然学过一些前端,但是项目里并没有用到任何jav ...
- jvm调优相关
查找占用cpu过高的线程,并排查原因 1.查找jvm进程 (1)jps -l (2)ps -ef|grep java 这一步骤可以得到进程号,假如进程号为9527 2.查找该jvm进程中占用cpu比较 ...
- jQuery常用知识点大总结
目录 jQuery jQuery介绍 jQuery的优势 jQuery的引入方式有两种: jQuery对象和dom对象 jQuery选择器 基本选择器(同css) 基本筛选器(选择之后进行过滤): 属 ...
- CSS两列布局
方法1:左边设置绝对定位,右边设置左外边距,大小和左边的宽度相等 //CSS部分: .contain{ position :relative; height: 300px; } .left{ posi ...
- ORACLE 清理SYSAUX表空间
在数据库检查中发现SYSAUX表空间占用过大,SYSAUX是ORACLE10G开始提供的功能,用于数据库为SYSTEM表空间减负. 用以下语句查出相应的表空间值 select a.tablespace ...