BZOJ3224 普通平衡树
Treap 版本:
//OJ 1999
//by Cydiater
//2016.8.30
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <queue>
#include <map>
#include <ctime>
#include <cmath>
#include <algorithm>
#include <string>
#include <iomanip>
using namespace std;
#define ll long long
#define up(i,j,n) for(int i=j;i<=n;i++)
#define down(i,j,n) for(int i=j;i>=n;i--)
const int MAXN=1e5+5;
const int oo=0x3f3f3f3f;
inline ll read(){
char ch=getchar();ll x=0,f=1;
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int N,op,num,root=0,tol=0,ans=0;
struct node{
int leftt,rightt,v,cnt,rnd,siz;
}t[MAXN];
namespace solution{
void updata(int k){
t[k].siz=t[t[k].leftt].siz+t[t[k].rightt].siz+t[k].cnt;
}
void lefturn(int &k){
int tt=t[k].rightt;t[k].rightt=t[tt].leftt;t[tt].leftt=k;
t[tt].siz=t[k].siz;updata(k);k=tt;
}
void righturn(int &k){
int tt=t[k].leftt;t[k].leftt=t[tt].rightt;t[tt].rightt=k;
t[tt].siz=t[k].siz;updata(k);k=tt;
}
void insert(int &k,int x){
if(k==0){
tol++;k=tol;t[k].siz=t[k].cnt=1;
t[k].v=x;t[k].rnd=rand();
return;
}
t[k].siz++;
if(t[k].v==x) t[k].cnt++;
else if(x>t[k].v){
insert(t[k].rightt,x);
if(t[t[k].rightt].rnd<t[k].rnd)lefturn(k);
}else{
insert(t[k].leftt,x);
if(t[t[k].leftt].rnd<t[k].rnd)righturn(k);
}
}
void del(int &k,int x){
if(k==0) return;
if(t[k].v==x){
if(t[k].cnt>1){t[k].cnt--;t[k].siz--;return;}
if(t[k].leftt*t[k].rightt==0)k=t[k].leftt+t[k].rightt;
else if(t[t[k].leftt].rnd<t[t[k].rightt].rnd){
righturn(k);del(k,x);
}else{
lefturn(k);del(k,x);
}
}else if(x>t[k].v){
t[k].siz--;
del(t[k].rightt,x);
}else{
t[k].siz--;
del(t[k].leftt,x);
}
}
int query_rank(int k,int x){
if(k==0)return 0;
if(t[k].v==x) return t[t[k].leftt].siz+1;
else if(x>t[k].v) return t[t[k].leftt].siz+t[k].cnt+query_rank(t[k].rightt,x);
else return query_rank(t[k].leftt,x);
}
int query_num(int k,int x){
if(k==0) return 0;
if(x<=t[t[k].leftt].siz) return query_num(t[k].leftt,x);
else if(x>t[t[k].leftt].siz+t[k].cnt) return query_num(t[k].rightt,x-(t[t[k].leftt].siz+t[k].cnt));
else return t[k].v;
}
void query_pre(int k,int x){
if(k==0) return;
if(t[k].v<x){
ans=t[k].v;
query_pre(t[k].rightt,x);
}else query_pre(t[k].leftt,x);
}
void query_nxt(int k,int x){
if(k==0) return;
if(t[k].v>x){
ans=t[k].v;
query_nxt(t[k].leftt,x);
}else query_nxt(t[k].rightt,x);
}
void slove(){
N=read();
up(i,1,N){
op=read();num=read();
if(op==1)insert(root,num);
if(op==2)del(root,num);
if(op==3)printf("%d\n",query_rank(root,num));
if(op==4)printf("%d\n",query_num(root,num));
if(op==5){
query_pre(root,num);
printf("%d\n",ans);
}
if(op==6){
query_nxt(root,num);
printf("%d\n",ans);
}
}
}
}
int main(){
//freopen("input.in","r",stdin);
using namespace solution;
slove();
return 0;
}
Splay 版本:
//BZOJ 3224
//by Cydiater
//2016.9.3
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <ctime>
#include <cmath>
#include <iomanip>
using namespace std;
#define ll long long
#define up(i,j,n) for(int i=j;i<=n;i++)
#define down(i,j,n) for(int i=j;i>=n;i--)
const int MAXN=1e6+5;
inline int read(){
char ch=getchar();int x=0,f=1;
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int root=0,tol=0,N,op,num;
struct SplayTree{
int son[2],siz,cnt,fa,v;
}t[MAXN];
namespace solution{
inline int get(int x){return x==t[t[x].fa].son[1];}//get left or right son
inline void clear(int x){
t[x].son[0]=t[x].son[1]=t[x].cnt=t[x].v=t[x].fa=t[x].siz=0;
}//reset node after deleted
inline void updata(int x){//updata node after rotated
if(x){
t[x].siz=t[x].cnt;
if(t[x].son[0])t[x].siz+=t[t[x].son[0]].siz;
if(t[x].son[1])t[x].siz+=t[t[x].son[1]].siz;
}
}
inline void rotate(int x){//rotate now node to root
int old=t[x].fa,oldf=t[old].fa,which=get(x);
t[old].son[which]=t[x].son[which^1];t[t[old].son[which]].fa=old;
t[old].fa=x;t[x].son[which^1]=old;
t[x].fa=oldf;
if(oldf)t[oldf].son[t[oldf].son[1]==old]=x;
updata(old);updata(x);
}
inline void splay(int x){
for(int fa;(fa=t[x].fa);rotate(x))if(t[fa].fa)
rotate((get(x)==get(fa)?fa:x));root=x;
}
inline void insert(int v){
if(root==0){
root=++tol;
t[root].son[0]=t[root].son[1]=t[root].fa=0;
t[root].v=v;t[root].cnt=t[root].siz=1;
return;
}
int now=root,fa=0;
while(1){
if(t[now].v==v){
t[now].cnt++;updata(now);updata(fa);
splay(now);break;
}
fa=now;now=t[now].son[t[now].v<v];
if(now==0){
now=++tol;
t[now].son[0]=t[now].son[1]=0;t[now].v=v;
t[now].siz=t[now].cnt=1;t[now].fa=fa;
t[fa].son[t[fa].v<v]=tol;
updata(fa);
splay(now);
break;
}
}
}
inline int find(int v){
int ans=0,now=root;
while(1){
if(v<t[now].v)now=t[now].son[0];
else{
ans+=(t[now].son[0]?t[t[now].son[0]].siz:0);
if(v==t[now].v){splay(now);return ans+1;}
ans+=t[now].cnt;
now=t[now].son[1];
}
}
}
inline int get_rank(int x){
int now=root;
while(1){
if(t[now].son[0]&&x<=t[t[now].son[0]].siz)now=t[now].son[0];
else{
int tmp=(t[now].son[0]?t[t[now].son[0]].siz:0)+t[now].cnt;
if(x<=tmp) return t[now].v;
x-=tmp;now=t[now].son[1];
}
}
}
inline int pre(){
int now=t[root].son[0];
while(t[now].son[1])now=t[now].son[1];
return now;
}
inline int nxt(){
int now=t[root].son[1];
while(t[now].son[0])now=t[now].son[0];
return now;
}
inline void del(int x){
int whatever=find(x);
if(t[root].cnt>1){
t[root].cnt--;
t[root].siz--;
return;
}
if(t[root].son[0]+t[root].son[1]==0){
clear(root);root=0;
return;
}
if(!t[root].son[0]){
int oldroot=root;root=t[root].son[1];t[root].fa=0;
clear(oldroot);return;
}else if(!t[root].son[1]){
int oldroot=root;root=t[root].son[0];t[root].fa=0;
clear(oldroot);return;
}
int leftbig=pre(),oldroot=root;
splay(leftbig);
t[t[oldroot].son[1]].fa=root;
t[root].son[1]=t[oldroot].son[1];
clear(oldroot);
updata(root);
return;
}
void debug(int now){
printf("now=%d t[now].son[0]=%d t[now].son[1]=%d t[now].siz=%d t[now].cnt=%d t[now].fa=%d t[now].v=%d\n",now,t[now].son[0],t[now].son[1],t[now].siz,t[now].cnt,t[now].fa,t[now].v);
if(t[now].son[0])debug(t[now].son[0]);
if(t[now].son[1])debug(t[now].son[1]);
}
}
int main(){
//freopen("input.in","r",stdin);
using namespace solution;
N=read();
while(N--){
op=read();num=read();
if(op==1)insert(num);
if(op==2)del(num);
if(op==3)printf("%d\n",find(num));
if(op==4)printf("%d\n",get_rank(num));
if(op==5){
insert(num);printf("%d\n",t[pre()].v);del(num);
}
if(op==6){
insert(num);printf("%d\n",t[nxt()].v);del(num);
}
//debug(root);
//puts("");
}
return 0;
}
关于Splay写的很好的一个博客:
BZOJ3224 普通平衡树的更多相关文章
- [BZOJ3224]普通平衡树(旋转treap,STL-vector)
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 20328 Solved: 8979[Submit][St ...
- [bzoj3224]普通平衡树/3223文艺平衡树
这是一道很普通的题.. 最近花了很多时间来想要去干什么,感觉自己还是太拿衣服 做这道题是因为偶尔看到了lavender的blog和她的bzoj早期AC记录,就被题目深深地吸引到了,原因有二: 自己sp ...
- BZOJ3224普通平衡树【Splay】
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 11751 Solved: 5013 Descriptio ...
- [TYVJ1728/BZOJ3224]普通平衡树-替罪羊树
Problem 普通平衡树 Solution 本题是裸的二叉平衡树.有很多种方法可以实现.这里打的是替罪羊树模板. 此题极其恶心. 前驱后继模块需要利用到rank模块来换一种思路求. 很多细节的地方容 ...
- [转载]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)
转载自ZZH大佬,原文:http://www.cnblogs.com/LadyLex/p/7182491.html 今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和t ...
- [您有新的未分配科技点]无旋treap:从好奇到入门(例题:bzoj3224 普通平衡树)
今天我们来学习一种新的数据结构:无旋treap.它和splay一样支持区间操作,和treap一样简单易懂,同时还支持可持久化. 无旋treap的节点定义和treap一样,都要同时满足树性质和堆性质,我 ...
- bzoj3224 普通平衡树(c++vector)
Tyvj 1728 普通平衡树 2014年8月23日6,4365 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有 ...
- BZOJ3224普通平衡树——非旋转treap
题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数, ...
- BZOJ3224普通平衡树——旋转treap
题目: 此为平衡树系列第一道:普通平衡树您需要写一种数据结构,来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个)3. 查询x数的排名(若有多个相同的数, ...
- BZOJ3224普通平衡树
洛谷题面链接 很早就过了,太久没打了,原本是在noip前用来练emacs的手感的. noip炸了,就滚回来更博客了(安排的计数任务刷不动,学不会容斥,打发时间...) 众所周知,splay是个好算法, ...
随机推荐
- ionic —— 开发环境搭建并编译运行第一个APP
其实类似的环境已经玩了很多次了,最开始玩还是微信刚刚出来,那会儿没有智能机.只好安装一个模拟器,却只是为了注册一个微信.想想也就是够了~ 前前后后折腾了很多次,可是每一次都给人不一样的感觉,也许是这个 ...
- apache配置虚拟主机
步骤如下: 1.在配置文件httpd.conf中启用httpd-vhosts.conf 找到# Virtual hosts将Include conf/extra/httpd-vhosts.conf前的 ...
- 如何快速从一个Storage Account拷贝到另一个账号
当您有两个Storage Account的时候,怎样快速做到从一个账号拷贝到另一个账号呢.当拷贝的文件比较,例如100多G(VHD文件). http://code.msdn.microsoft.com ...
- js自定义事件
自定义事件的本质,创建一个对象,然后把事件的名字作为对象的一个属性,然后value是一个[],把此事件的所以回调都push进去. 写一个很基本的,没有把对象暴露出去的js的自定义事件. var eve ...
- iOS -- 上传多张图片 后台(PHP)代码和上传一张的一样
// 上传多张图片 - (void)send { // 设置初始记录量为0 self.count = 0; self.upcount = 0; // 设置初始值为NO self.isUploadPic ...
- 39-tar 打包压缩
将文件存储到归档文件中或者从归档文件中获取原始文件,以及为文件创建归档文件 tar [option] [modifiers] [file-list] 参数 file-list是tar进行归档和提取的文 ...
- Collection中Set集合在应用中常见的方法和注意点
Set集合 : 元素无序的,元素不允许重复. ---->HashSet : 存值方式使用哈希表来存值的. 原理 : 如果HashSet中存放对象 ...
- 我的一个小作品 android App ---校园资讯助手
软件主界面采用Fragment+ViewPager组成.在点开后将会自动对学校新闻页面使用URl类来抓取,然后对网页中的信息提取,使用WebView来loadData在主界面上面显示, 为了使 ...
- [转]hibernate在eclipse的逆向工程生成hbm.xml和bean类
原文地址:http://www.xuebuyuan.com/210489.html 以前一直用myelipse,在myeclipse做hibernate逆向工程倒是很顺手了. 可是最近改用eclips ...
- iOS开发小技巧--利用MJExtension解决数据结构复杂的模型转换
一.开发中难免会遇到,系统返回的数据中字典套集合,集合里面又套一层字典,然后字典里面还有字典或者集合等等的复杂结构的数据...MJExtension轻松搞定这类问题 1.解决方法一: 例:百思项目中帖 ...