P3369 【模板】普通平衡树 (splay 模板)
题目描述
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
插入x数
删除x数(若有多个相同的数,因只删除一个)
查询x数的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
查询排名为x的数
求x的前驱(前驱定义为小于x,且最大的数)
求x的后继(后继定义为大于x,且最小的数) 
输入输出格式
输入格式: 
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号( 1 \leq opt \leq 6 1≤opt≤6 )
输出格式: 
对于操作3,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 
说明
时空限制:1000ms,128M
n的数据范围:n≤100000
code:
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<ctime>
using namespace std;
const int MAX=200010;
int n,opt,x,root,sz;
int node[MAX][2],size[MAX],fa[MAX],cnt[MAX],key[MAX];
inline void clear(int x) {
    node[x][1]=node[x][0]=size[x]=fa[x]=cnt[x]=key[x]=0;
}
inline bool get(int x) {
    return node[fa[x]][1]==x;
}
inline void update(int x){
    if(x) {
        size[x]=cnt[x];
        if(node[x][1]) size[x]+=size[node[x][1]];
        if(node[x][0]) size[x]+=size[node[x][0]];
    }
}
inline void rotate(int x) {
    int old=fa[x],oldf=fa[old],which=get(x);
    node[old][which]=node[x][which^1]; fa[node[old][which]]=old;
    fa[old]=x; node[x][which^1]=old;
    fa[x]=oldf;
    if(oldf) node[oldf][node[oldf][1]==old]=x;
    update(old);update(x);
}
inline void splay(int x) {
    for(int f;f=fa[x];rotate(x))
        if(fa[f]){
            if(get(x)==get(f)) rotate(f);
            else rotate(x);
        }
    root=x;
}
inline void insert(int x) {
    if(!root) {
        sz++;root=sz;
        node[sz][0]=node[sz][1]=fa[sz]=0;
        size[sz]=cnt[sz]=1;
        key[sz]=x;
        return ;
    }
    int now=root,f=0;
    while(1) {
        if(key[now]==x) {
            cnt[now]++;update(now);update(f);splay(now);break;
        }
        f=now;
        now=node[now][key[now]<x];
        if(now==0) {
            sz++;
            node[sz][0]=node[sz][1]=0;
            size[sz]=cnt[sz]=1;
            fa[sz]=f;key[sz]=x;
            node[f][key[f]<x]=sz;
            update(f);
            splay(sz);//为pre和next做准备
            break;
        }
    }
}
inline int find1(int x) {
    int ans=0,now=root;
    while(1){
        if(x<key[now]) now=node[now][0];
        else {
            ans+=node[now][0]?size[node[now][0]]:0;
            if(x==key[now]) {
                splay(now);
                return ans+1;
            }
            else {
                ans+=cnt[now];
                now=node[now][1];
            }
        }
    }
}
inline int find2(int x) {
    int now=root;
    while(1){
        if(node[now][0]&&x<=size[node[now][0]])
            now=node[now][0];
        else {
            int temp=(node[now][0]?size[node[now][0]]:0)+cnt[now];
            if(x<=temp) return key[now];
            x-=temp,now=node[now][1];
        }
    }
}
inline int pre() {
    int now=node[root][0];
    while(node[now][1]) now=node[now][1];
    return now;
}
inline int next() {
    int now=node[root][1];
    while(node[now][0]) now=node[now][0];
    return now;
}
inline void del(int x) {
    find1(x);
    if(cnt[root]>1) {
        cnt[root]--;
        update(root);
    }
    else if(!node[root][0]&&!node[root][1]) {
        clear(root);root=0;
    }
    else if(!node[root][0]) {
        int old=root;
        root=node[root][1];
        fa[root]=0;
        clear(old);
    }
    else if(!node[root][1]) {
        int old=root;
        root=node[root][0];
        fa[root]=0;
        clear(old);
    }
    else {
        int lbig=pre(),old=root;
        splay(lbig);
        node[root][1]=node[old][1];
        fa[node[old][1]]=root;
        clear(old);
        update(root);
    }
    return ;
}
int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        scanf("%d %d",&opt,&x);
        switch(opt) {
            case 1:insert(x);break;
            case 2:del(x);break;
            case 3:printf("%d\n",find1(x));break;
            case 4:printf("%d\n",find2(x));break;
            case 5:insert(x);printf("%d\n",key[pre()]);del(x);break;
            case 6:insert(x);printf("%d\n",key[next()]);del(x);break;
        }
    }
    return 0;
}P3369 【模板】普通平衡树 (splay 模板)的更多相关文章
- luoguP3391[模板]文艺平衡树(Splay)  题解
		链接一下题目:luoguP3391[模板]文艺平衡树(Splay) 平衡树解析 这里的Splay维护的显然不再是权值排序 现在按照的是序列中的编号排序(不过在这道题目里面就是权值诶...) 那么,继续 ... 
- [洛谷P3391] 文艺平衡树 (Splay模板)
		初识splay 学splay有一段时间了,一直没写...... 本题是splay模板题,维护一个1~n的序列,支持区间翻转(比如1 2 3 4 5 6变成1 2 3 6 5 4),最后输出结果序列. ... 
- [luogu3369/bzoj3224]普通平衡树(splay模板、平衡树初探)
		解题关键:splay模板题整理. 如何不加入极大极小值?(待思考) #include<cstdio> #include<cstring> #include<algorit ... 
- bzoj3224  普通平衡树              splay模板
		题目传送门 题目大意:完成一颗splay树. 思路:模板题,学着还是很有意思的. 学习splay树:蒟蒻yyb 该题模板:汪立超 #include<bits/stdc++.h> #defi ... 
- bzoj3224 普通平衡树(splay 模板)
		3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 11427 Solved: 4878[Submit][St ... 
- 洛谷.3369.[模板]普通平衡树(Splay)
		题目链接 第一次写(2017.11.7): #include<cstdio> #include<cctype> using namespace std; const int N ... 
- 洛谷.3391.[模板]文艺平衡树(Splay)
		题目链接 //注意建树 #include<cstdio> #include<algorithm> const int N=1e5+5; //using std::swap; i ... 
- [bzoj3224]Tyvj 1728 普通平衡树——splay模板
		题目 你需要写一种数据结构支援以下操作. 插入元素. 删除元素. 查询元素的排名. 查询第k小的元素. 查询元素前趋. 查询元素后继. 题解 BBST裸题. 代码 #include <cstdi ... 
- 【洛谷P3369】普通平衡树——Splay学习笔记(一)
		二叉搜索树(二叉排序树) 概念:一棵树,若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值: 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值: 它的左.右子树也分别为二叉搜索树 ... 
随机推荐
- @Service注解的作用
			@Service注解作用 1. 其getBean的默认名称是类名(头字母小写),可以@Service(“xxxx”)这样来指定, 2.其定义的bean默认是单例的,可以使用@Service(“b ... 
- POJ 2079
			呃,不知道我用的算不算卡壳,总有点枚举的意思. 先求凸包,然后,枚举其中一点,再枚举另一点作为结尾,这个向量旋转一周后,求出最大值面积.这里面用的是旋转卡壳判断的那个式子. PS:下一篇和这题是一样题 ... 
- iOS 8 UI布局 AutoLayout及SizeClass(二)
			一.新特性Size Class介绍 随着iOS8系统的公布,一个全新的页面UI布局概念出现,这个新特性将颠覆包含iOS7及之前版本号的UI布局方式,这个新特性就是Size Class. Size Cl ... 
- Linux命令(八)——vi编辑器的使用
			vi编辑器是linux系统下的标准正文编辑器,有三种基本模式:命令行模式.插入模式和底行命令模式. 1.命令行模式:控制屏幕光标的移动,字符.字或行的删除,移动复制某区段及进入插入模式或底行命令模式下 ... 
- beisen
			#include <stdio.h> #include <pthread.h> #include <windows.h> #define N 100 #define ... 
- hdoj--5093--Battle ships(二分图经典建图)
			Battle ships Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Tot ... 
- [Javascript] 轻量级的JavaScript日期处理类库xDate使用指南
			XDate是一个请谅解的JavaScript的原生Date对象的封装库,提供增强的功能解析,格式化和日期处理.使用起来就和JavaScript自己的对象和方法一样,非常简单. XDate是一个请谅解的 ... 
- WPF黑色背景下常用控件样式
			平时工作用 自己整理的 代码等找到合适的上传空间在进行同步 
- .net中的TreeView的数据绑定与EasyUi_tree的数据绑定
			昨天看到了.net中的TreeView,学习了一波TreeView的数据绑定,联想到EasyUi中的Tree的数据,觉得里面的逻辑差不多,就总结了一下两者的数据绑定. 前端页面和必要的JS如下 < ... 
- C# 线程知识汇总
			一.基本概念 进程(process)是windows系统中你的一个基本概念,它包含着一个运行程序所需要的资源.一个正在运行的应用程序在操作系统中被视为一个进程,进程可以包括一个或者多个线程.线程是操作 ... 
