★★★   输入文件: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

【提示】

1.n的数据范围:n<=100000
2.每个数的数据范围:[-1e7,1e7]

  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 ;
}

最新文章

  1. 【贪心】HDU 1257
  2. [Machine Learning] 机器学习常见算法分类汇总
  3. jshzoi
  4. StackGAN: Text to Photo-realistic Image Synthesis with Stacked Generative Adversarial Networks 论文笔记
  5. MUMmer 3使用方法
  6. 【Todo】LR-逻辑回归
  7. codeblocks调试快捷键说明
  8. 很赞的MathJax
  9. HDU 2669 第六周 I题
  10. opencv中stitching_detail的运行
  11. getComputedStyle与currentStyle
  12. 【三】注入框架RoboGuice使用:(Your First Resource Injection)
  13. message from server: &quot;Host &#39;xxx&#39; is not allowed to connect to this MySQL server的解决
  14. 基于Redis的在线用户列表解决方案
  15. Python学习---字符串处理
  16. AES 加密与解密
  17. TensorFlow - 在 windows 系统上安装
  18. zookeeper集群操作【这里只说明简单的操作步骤,zk的相关参数、说明请参考官方文档】
  19. 网络IP地址
  20. MiniDP与HDMI的关系

热门文章

  1. SaltStack远程执行
  2. Spark 源码分析 &ndash; BlockManagerMaster&amp;Slave
  3. 解决从Windows拷贝来的文件到Ubuntu出现乱码的问题
  4. linux页缓存
  5. python一两行代码完成的骚操作
  6. 17.出现fatal signal(SIGSEGV),code 1,fault addr 0x0 in tid 29931的问题
  7. su 与 su - 区别
  8. HDevelop数据类型
  9. gdb core
  10. CSS实现文本超过指定长度显示省略号