COJS:1829. [Tyvj 1728]普通平衡树
★★★ 输入文件:phs.in
输出文件:phs.out
简单对比
时间限制:1 s 内存限制:128 MB
【题目描述】
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
【输入格式】
第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6)
【输出格式】
对于操作3,4,5,6每行输出一个数,表示对应答案
【样例输入】
- 10
- 1 106465
- 4 1
- 1 317721
- 1 460929
- 1 644985
- 1 84185
- 1 89851
- 6 81968
- 1 492737
- 5 493598
【样例输出】
- 106465
- 84185
- 492737
【提示】
SBT版的:
- #include<bits/stdc++.h>
- using namespace std;
- const int maxn=;
- int root,tot,N;
- int key[maxn],siz[maxn],lc[maxn],rc[maxn];
- void r_rotate(int &rt){
- int k=lc[rt];
- lc[rt]=rc[k];
- rc[k]=rt;
- siz[k]=siz[rt];
- siz[rt]=siz[lc[rt]]+siz[rc[rt]]+;
- rt=k;
- }
- void l_rotate(int &rt){
- int k=rc[rt];
- rc[rt]=lc[k];
- lc[k]=rt;
- siz[k]=siz[rt];
- siz[rt]=siz[lc[rt]]+siz[rc[rt]]+;
- rt=k;
- }
- void MAINTAIN(int &rt,bool flag){
- if(flag==false){//rt的左子树的某子树>rt的右子树
- if(siz[lc[lc[rt]]]>siz[rc[rt]]) r_rotate(rt);//如果rt的左孩子的左孩子>rt的右孩子,rt右旋
- else if(siz[rc[lc[rt]]]>siz[rc[rt]]){//如果rt的左孩子L的右孩子B > rt的右孩子R:
- l_rotate(lc[rt]);//先让rt的左孩子左旋,使rt的左子树变成以B为根
- r_rotate(rt);//再右旋再变成以B为根
- }
- else return;//平衡
- }
- else{//rt的右子树的某子树>rt的左子树
- if(siz[rc[rc[rt]]]>siz[lc[rt]]) l_rotate(rt);
- else if(siz[lc[rc[rt]]]>siz[lc[rt]]){
- r_rotate(rc[rt]);
- l_rotate(rt);
- }
- else return;
- }
- MAINTAIN(lc[rt],); MAINTAIN(rc[rt],);//检查是否满足平衡
- MAINTAIN(rt,); MAINTAIN(rt,);
- }
- void insert(int &rt,int v){
- if(rt==){//找到合适的位置插入
- rt=++tot;
- key[rt]=v;
- lc[rt]=rc[rt]=; siz[rt]=;
- return ;
- }
- siz[rt]++;
- if(v<=key[rt]) insert(lc[rt],v);
- else insert(rc[rt],v);
- MAINTAIN(rt,v>key[rt]);//调整树结构
- }
- int Delete(int &rt,int v){
- int ans;
- siz[rt]--;
- if(v==key[rt]||(v<key[rt]&&lc[rt]==)||(v>key[rt]&&rc[rt]==)){
- ans=key[rt];
- if(lc[rt]==||rc[rt]==) rt=lc[rt]+rc[rt];//没有左子树或者右子树,直接利用&操作,相当于直接以子树接到上个节点
- else key[rt]=Delete(lc[rt],key[rt]+);//返回左子树中的最大值,然后替换当前的rt,相当于删掉当前节点,用左子树中最大值放在这个位置来代替
- return ans;
- }
- if(v<key[rt]) ans=Delete(lc[rt],v);
- else ans=Delete(rc[rt],v);
- return ans;
- }
- bool find(int &rt,int v){//查找是否有 key值为 v的节点
- if(rt==) return false;
- else if(v==key[rt]) return true;
- else if(v<key[rt]) return find(lc[rt],v);
- else if(v>key[rt]) return find(rc[rt],v);
- }
- int rank(int &rt,int v){//询问排名
- if(rt==) return ;
- if(v<=key[rt]) return rank(lc[rt],v);
- else return siz[lc[rt]]++rank(rc[rt],v);
- }
- /*
- 如果元素唯一的话,可以这么写:
- int rank(int &rt,int v){
- if(rt==0) return 1;
- if(v==key[rt]) return siz[lc[rt]]+1;
- if(v<key[rt]) return rank(lc[rt],v);
- return siz[lc[rt]]+1+rank(rc[rt],v);
- }
- 但此题不行
- */
- int select(int &rt,int k){//返回在v位置上的节点,可以改造成取大和取小函数
- if(k==siz[lc[rt]]+) return key[rt];
- if(k<=siz[lc[rt]]) return select(lc[rt],k);
- else return select(rc[rt],k--siz[lc[rt]]);
- }
- int pred(int &rt,int v){//返回比 v小的最大的数
- if(rt==) return v;//要求是比v小,返回v的意思是没找到
- if(v<=key[rt]) return pred(lc[rt],v);//key[rt]>v 必然要往更小的方向,即rt的左子树
- else{//此时 key[rt]<v,而rt的右子树的key值都大于key[rt]
- int ans=pred(rc[rt],v);
- if(ans==v) return key[rt];//返回v表示rt的右子树中的key都比v大,返回key[rt]
- return ans;
- }
- }
- int succ(int &rt,int v){//返回比v大的最小的数
- if(rt==) return v;
- if(v>=key[rt]) return succ(rc[rt],v);
- else{
- int ans=succ(lc[rt],v);
- if(ans==v) return key[rt];
- return ans;
- }
- }
- void inorder(int rt){//输出中序遍历
- if(rt!=){
- inorder(lc[rt]);
- cout<<key[rt]<<" ";
- inorder(rc[rt]);
- }
- }
- int main(){
- siz[]=root=tot=;
- scanf("%d",&N);
- for(int i=,kin,num;i<=N;i++){
- scanf("%d%d",&kin,&num);
- if(kin==) insert(root,num);
- else if(kin==) Delete(root,num);
- else if(kin==) printf("%d\n",rank(root,num));
- else if(kin==) printf("%d\n",select(root,num));
- else if(kin==) printf("%d\n",pred(root,num));
- else if(kin==) printf("%d\n",succ(root,num));
- }
- return ;
- }
无注释版的:
- #include<bits/stdc++.h>
- using namespace std;
- const int maxn=;
- int root,tot,N;
- int key[maxn],siz[maxn],lc[maxn],rc[maxn];
- void r_rotate(int &rt){
- int k=lc[rt];
- lc[rt]=rc[k];
- rc[k]=rt;
- siz[k]=siz[rt];
- siz[rt]=siz[lc[rt]]+siz[rc[rt]]+;
- rt=k;
- }
- void l_rotate(int &rt){
- int k=rc[rt];
- rc[rt]=lc[k];
- lc[k]=rt;
- siz[k]=siz[rt];
- siz[rt]=siz[lc[rt]]+siz[rc[rt]]+;
- rt=k;
- }
- void MAINTAIN(int &rt,bool flag){
- if(flag==false){
- if(siz[lc[lc[rt]]]>siz[rc[rt]]) r_rotate(rt);
- else if(siz[rc[lc[rt]]]>siz[rc[rt]]){
- l_rotate(lc[rt]);
- r_rotate(rt);
- }
- else return;
- }
- else{
- if(siz[rc[rc[rt]]]>siz[lc[rt]]) l_rotate(rt);
- else if(siz[lc[rc[rt]]]>siz[lc[rt]]){
- r_rotate(rc[rt]);
- l_rotate(rt);
- }
- else return;
- }
- MAINTAIN(lc[rt],); MAINTAIN(rc[rt],);
- MAINTAIN(rt,); MAINTAIN(rt,);
- }
- void insert(int &rt,int v){
- if(rt==){
- rt=++tot;
- key[rt]=v;
- lc[rt]=rc[rt]=; siz[rt]=;
- return ;
- }
- siz[rt]++;
- if(v<=key[rt]) insert(lc[rt],v);
- else insert(rc[rt],v);
- MAINTAIN(rt,v>key[rt]);
- }
- int Delete(int &rt,int v){
- int ans;
- siz[rt]--;
- if(v==key[rt]||(v<key[rt]&&lc[rt]==)||(v>key[rt]&&rc[rt]==)){
- ans=key[rt];
- if(lc[rt]==||rc[rt]==) rt=lc[rt]+rc[rt];
- else key[rt]=Delete(lc[rt],key[rt]+);
- return ans;
- }
- if(v<key[rt]) ans=Delete(lc[rt],v);
- else ans=Delete(rc[rt],v);
- return ans;
- }
- bool find(int &rt,int v){
- if(rt==) return false;
- else if(v==key[rt]) return true;
- else if(v<key[rt]) return find(lc[rt],v);
- else if(v>key[rt]) return find(rc[rt],v);
- }
- int rank(int &rt,int v){
- if(rt==) return ;
- if(v<=key[rt]) return rank(lc[rt],v);
- else return siz[lc[rt]]++rank(rc[rt],v);
- }
- int select(int &rt,int k){
- if(k==siz[lc[rt]]+) return key[rt];
- if(k<=siz[lc[rt]]) return select(lc[rt],k);
- else return select(rc[rt],k--siz[lc[rt]]);
- }
- int pred(int &rt,int v){
- if(rt==) return v;
- if(v<=key[rt]) return pred(lc[rt],v);
- else{
- int ans=pred(rc[rt],v);
- if(ans==v) return key[rt];
- return ans;
- }
- }
- int succ(int &rt,int v){
- if(rt==) return v;
- if(v>=key[rt]) return succ(rc[rt],v);
- else{
- int ans=succ(lc[rt],v);
- if(ans==v) return key[rt];
- return ans;
- }
- }
- void inorder(int rt){
- if(rt!=){
- inorder(lc[rt]);
- cout<<key[rt]<<" ";
- inorder(rc[rt]);
- }
- }
- int main(){
- siz[]=root=tot=;
- scanf("%d",&N);
- for(int i=,kin,num;i<=N;i++){
- scanf("%d%d",&kin,&num);
- if(kin==) insert(root,num);
- else if(kin==) Delete(root,num);
- else if(kin==) printf("%d\n",rank(root,num));
- else if(kin==) printf("%d\n",select(root,num));
- else if(kin==) printf("%d\n",pred(root,num));
- else if(kin==) printf("%d\n",succ(root,num));
- }
- return ;
- }
Splay版的:
- #include<iostream>
- #include<cstdio>
- #include<cstdlib>
- #include<cmath>
- #include<algorithm>
- #include<queue>
- #include<vector>
- using namespace std;
- const int maxn=;
- int key[maxn],lc[maxn],rc[maxn],fa[maxn],siz[maxn];
- int tot,root;
- int T;
- void update(int x){
- siz[x]=siz[lc[x]]++siz[rc[x]];
- }
- void r_rotate(int x){
- int y=fa[x];
- lc[y]=rc[x];
- if(rc[x]!=) fa[rc[x]]=y;
- fa[x]=fa[y];
- if(y==lc[fa[y]]) lc[fa[y]]=x;
- else rc[fa[y]]=x;
- fa[y]=x; rc[x]=y;
- update(x); update(y);
- }
- void l_rotate(int x){
- int y=fa[x];
- rc[y]=lc[x];
- if(lc[x]!=) fa[lc[x]]=y;
- fa[x]=fa[y];
- if(y==lc[fa[y]]) lc[fa[y]]=x;
- else rc[fa[y]]=x;
- fa[y]=x; lc[x]=y;
- update(x); update(y);
- }
- void splay(int x,int s){
- int p;
- while(fa[x]!=s){
- p=fa[x];
- if(fa[p]==s){
- if(x==lc[p]) r_rotate(x);
- else l_rotate(x);
- break;
- }
- if(x==lc[p]){
- if(p==lc[fa[p]]) r_rotate(p),r_rotate(x);
- else r_rotate(x),l_rotate(x);
- }
- else{
- if(p==rc[fa[p]]) l_rotate(p),l_rotate(x);
- else l_rotate(x),r_rotate(x);
- }
- }
- if(s==) root=x;
- update(x);
- }
- int find(int v){//查找在这棵树中键值为v的节点
- int x=root;
- while(x!=){
- if(v<key[x]) x=lc[x];
- else if(v>key[x]) x=rc[x];
- else if(v==key[x]){
- splay(x,);
- return x;
- }
- }
- return -;
- }
- void New_node(int &x,int fath,int v){//建立新节点
- x=++tot;
- lc[x]=rc[x]=; siz[x]=;
- fa[x]=fath;
- key[x]=v;
- }
- void insert(int v){//插入新节点
- if(root==){
- New_node(rc[],,v);
- root=tot;
- return ;
- }
- int p,x=root;
- while(x!=){
- p=x;
- if(v<=key[x]) siz[x]++,x=lc[x];
- else siz[x]++,x=rc[x];
- }
- if(v<=key[p]) New_node(lc[p],p,v);
- else New_node(rc[p],p,v);
- splay(tot,);
- }
- int getmax(int x){//找到以x为根的最大值
- if(rc[x]!=) return getmax(rc[x]);
- return x;
- }
- int getmin(int x){//找到以x为根的最小值
- if(lc[x]!=) return getmin(lc[x]);
- return x;
- }
- int getpre(int x){//找到节点x的前驱
- splay(x,);
- return getmax(lc[x]);
- }
- int getne(int x){//找到节点x的后继
- splay(x,);
- return getmin(rc[x]);
- }
- void Delete(int v){
- int x=find(v);
- int pp=getmax(lc[x]);
- int nn=getmin(rc[x]);
- if(lc[x]==||rc[x]==){
- if(lc[x]==&&rc[x]==){
- root=; rc[]=;
- return ;
- }
- if(lc[x]==){
- rc[]=rc[x]; fa[rc[x]]=; root=rc[x]; rc[x]=;
- siz[x]=;
- return ;
- }
- else{
- rc[]=lc[x]; fa[lc[x]]=; root=lc[x]; lc[x]=;
- siz[x]=;
- return ;
- }
- }
- splay(pp,);
- splay(nn,root);
- fa[lc[nn]]=; siz[lc[nn]]=; lc[nn]=;
- update(nn); update(pp);
- }
- int rank(int rt,int v){//返回键值为v的节点的排名
- if(rt==) return ;
- if(v<=key[rt]) return rank(lc[rt],v);
- else return siz[lc[rt]]++rank(rc[rt],v);
- }
- int findkth(int x,int k){//在以x为根的树中找第 k大
- if(siz[lc[x]]+==k) return key[x];
- if(siz[lc[x]]+>k) return findkth(lc[x],k);
- return findkth(rc[x],k-siz[lc[x]]-);
- }
- int pred(int rt,int v){//返回比 v小的最大的数
- if(rt==) return v;
- if(v<=key[rt]) return pred(lc[rt],v);
- else{
- int ans=pred(rc[rt],v);
- if(ans==v) return key[rt];
- return ans;
- }
- }
- int succ(int rt,int v){//返回比 v大的最小的数
- if(rt==) return v;
- if(v>=key[rt]) return succ(rc[rt],v);
- else{
- int ans=succ(lc[rt],v);
- if(ans==v) return key[rt];
- return ans;
- }
- }
- int main(){
- freopen("phs.in","r",stdin);
- freopen("phs.out","w",stdout);
- scanf("%d",&T);
- while (T--){
- int kin,num;
- scanf("%d%d",&kin,&num);
- if(kin==)
- insert(num);//插入
- else if(kin==)
- Delete(num);//删除(若有多个相同的数,只删除一个)
- else if(kin==)
- printf("%d\n",rank(root,num));//查询num数的排名(若有多个相同的数,因输出最小的排名)
- else if (kin==)
- printf("%d\n",findkth(root,num));//查询排名为x的数
- else if (kin==)
- printf("%d\n",pred(root,num));
- else if (kin==)
- printf("%d\n",succ(root,num));
- }
- return ;
- }
vector版的:
- #include<cstdio>
- #include<vector>
- #include<algorithm>
- using namespace std;
- const int INF=;
- int n;
- vector<int> tree;
- int find(int x){
- return lower_bound(tree.begin(),tree.end(),x)-tree.begin()+;
- }
- int main(){
- scanf("%d",&n);
- tree.reserve();
- for(int i=,kin,x;i<=n;i++){
- scanf("%d%d",&kin,&x);
- if(kin==) tree.insert(upper_bound(tree.begin(),tree.end(),x),x);
- else if(kin==) tree.erase(lower_bound(tree.begin(),tree.end(),x));
- else if(kin==) printf("%d\n",find(x));
- else if(kin==) printf("%d\n",tree[x-]);
- else if(kin==) printf("%d\n",*--lower_bound(tree.begin(),tree.end(),x));
- else if(kin==) printf("%d\n",*upper_bound(tree.begin(),tree.end(),x));
- }
- return ;
- }
COJS:1829. [Tyvj 1728]普通平衡树的更多相关文章
- cogs 1829. [Tyvj 1728]普通平衡树 权值线段树
1829. [Tyvj 1728]普通平衡树 ★★★ 输入文件:phs.in 输出文件:phs.out 简单对比时间限制:1 s 内存限制:1000 MB [题目描述] 您需要写一种数 ...
- [BZOJ3224]Tyvj 1728 普通平衡树
[BZOJ3224]Tyvj 1728 普通平衡树 试题描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除一个) ...
- BZOJ 3224: Tyvj 1728 普通平衡树
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 9629 Solved: 4091[Submit][Sta ...
- BZOJ 3224 TYVJ 1728 普通平衡树 [Treap树模板]
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 7390 Solved: 3122 [Submit][S ...
- BZOJ 3224: Tyvj 1728 普通平衡树 treap
3224: Tyvj 1728 普通平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除 ...
- BZOJ 3224: Tyvj 1728 普通平衡树 vector
3224: Tyvj 1728 普通平衡树 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:1. 插入x数2. 删除x数(若有多个相同的数,因只删除 ...
- bzoj3224 Tyvj 1728 普通平衡树(名次树+处理相同)
3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 5354 Solved: 2196[Submit][Sta ...
- BZOJ 3224: Tyvj 1728 普通平衡树(BST)
treap,算是模板题了...我中间还一次交错题... -------------------------------------------------------------------- #in ...
- [补档][Tyvj 1728]普通平衡树
[Tyvj 1728]普通平衡树 题目 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 1. 插入x数 2. 删除x数(若有多个相同的数,因只删除一个) 3. 查询x数的 ...
随机推荐
- 170418、vmware 安装 centos 开启网卡自启动
前言:CentOS虚拟机安装成功后,默认开机未启用网关,通过修改配置文件,启用网卡 开启方法如下: 1.登录系统,虚拟机安装完成后,第一次登录系统,系统只有一个账号,即超级管理员root账户,输入安装 ...
- 160408、SpringMVC整合Shiro
第一步:配置web.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <!-- 配置Shiro过滤器,先让Shiro过滤系统接收到的请求 --> ...
- Yii框架2.0的小部件
小部件是视图里的可重用单元. 小部件是在视图中使用的,但是可能需要使用控制器传给他的模型,比如在渲染表单的时候.比如一般的时间拾取器就可以直接砸视图里加入如下代码就可以: <?php use y ...
- C#中Datatable和List互相转换
其实早就该写的,哈哈,不过今天刚想起来注册,热热手,就写一下,哈哈. 直接上内容吧: 建立一个控制台应用程序, List<students> Studentlist = new List& ...
- ovn-kubernetes安装指南
Master节点的安装 1.首先在master节点安装ovs和ovn: #!/bin/bash sudo apt-get install openvswitch-common openvswitch- ...
- jquery prop attr
checked比较特殊,只要设置了属性checked,不管何值都是checked的.例如:<input type="checkbox" checked><inpu ...
- Java集合—List(转载)
本篇文章将集中介绍了List集合相比Collection接口增加的一些重要功能以及List集合的两个重要子类ArrayList及LinkedList. 一.List集合 List作为Collectio ...
- TraClus java版实现
前一阵子我们部门接到了业务那边的一个需求.想通过用户的wifi数据计算出商场内用户最喜爱走的线路.其实说白了就是用户轨迹聚类.根据业务的需求,我们最终采用了traClus聚类算法.tra ...
- Mysql—(2)—
数据库存储引擎 (更多详见) 一 什么是存储引擎 mysql中建立的库===>文件夹 库中建立的表===>文件 现实生活中我们用来存储数据的文件应该有不同的类型:比如存文本用txt类型,存 ...
- Embedding SQLite in a c programm
Embedding SQLite in a c programm The following program demonstrates how to embed SQLite into ...