van Emda Boas
van Emda Boas维护了一个整数集合[0,Max)(无重复),其中Max必须等于2的正整数次幂。它支持以下操作:
(1)插入一个数字;
(2)删除一个数字;
(3)询问某一个数字在不在这个集合中;
(4)询问集合的最大最小值;
(5)询问一个数字的前驱或者后继。
每个操作的复杂度最大为O(loglog(n))
#include <cmath>
#include <algorithm> /***
维护的集合范围为[0,MAXU-1]
MAXU必须为2的正整数次幂
MAXU<=2^30
***/ template<int MAXU>
class VanEmdeBoasTree
{
private: int m_inValidValue; struct TreeNode
{
int Min,Max; /**
u为2的某次幂
设u=2^k
若k为偶数 UpBit=k/2
若k为奇数 UpBit=(k+1)/2
DownBit=k-UpBit
**/
int u;
int UpBit;
int DownBit; TreeNode* summary;
TreeNode** cluster; /**
x的高UpBit位
**/
int high(int x)
{
return x>>DownBit;
} /**
x的低DownBit位
**/
int low(int x)
{
return x&((<<DownBit)-);
} int index(int hx,int lx)
{
return (hx<<DownBit)|lx;
}
};
TreeNode* m_root;
int m_MAXRANGE; /**
已知u=2^k 返回k
**/
int GetSumBit(const int u)
{
return int(log2(u)+0.5);
} void build(TreeNode* &root,const int u)
{
root->Min=m_inValidValue;
root->Max=m_inValidValue;
root->u=u; if(==u) return; const int k=GetSumBit(u);
root->UpBit=(k+)>>;
root->DownBit=k>>; root->summary=new TreeNode;
build(root->summary,<<root->UpBit); root->cluster=new TreeNode*[<<root->UpBit];
for(int i=;i<(<<root->UpBit);i++)
{
root->cluster[i]=new TreeNode;
build(root->cluster[i],<<root->DownBit);
}
} int GetMinValue(TreeNode *rt) { return rt->Min; }
int GetMaxValue(TreeNode *rt) { return rt->Max; } int getSuccessor(TreeNode* curNode,int x)
{
if(==curNode->u)
{
if(x==&&curNode->Max==) return ;
else return m_inValidValue;
}
else if(curNode->Min!=m_inValidValue&&x<curNode->Min)
{
return curNode->Min;
}
else
{
const int highX=curNode->high(x);
const int lowX=curNode->low(x); int MaxLow=GetMaxValue(curNode->cluster[highX]);
if(MaxLow!=m_inValidValue&&lowX<MaxLow)
{
return curNode->index(highX,
getSuccessor(curNode->cluster[highX],lowX));
}
else
{
int successCluster=getSuccessor(curNode->summary,highX);
if(successCluster==m_inValidValue) return m_inValidValue;
else
{
return curNode->index(successCluster,
GetMinValue(curNode->cluster[successCluster]));
}
}
}
} int getPredecessor(TreeNode* curNode,int x)
{
if(==curNode->u)
{
if(==x&&==curNode->Min) return ;
else return m_inValidValue;
}
else if(curNode->Max!=m_inValidValue&&x>curNode->Max)
{
return curNode->Max;
}
else
{
const int highX=curNode->high(x);
const int lowX=curNode->low(x); int MinLow=GetMinValue(curNode->cluster[highX]);
if(MinLow!=m_inValidValue&&lowX>MinLow)
{
return curNode->index(highX,
getPredecessor(curNode->cluster[highX],lowX));
}
else
{
int predCluster=getPredecessor(curNode->summary,highX);
if(predCluster==m_inValidValue)
{
if(curNode->Min!=m_inValidValue&&x>curNode->Min)
{
return curNode->Min;
}
else return m_inValidValue;
}
else
{
return curNode->index(predCluster,
GetMaxValue(curNode->cluster[predCluster]));
}
}
}
} void insertEmptyNode(TreeNode* curNode,int x)
{
curNode->Min=curNode->Max=x;
} void insert(TreeNode* curNode,int x)
{
if(curNode->Min==m_inValidValue)
{
insertEmptyNode(curNode,x);
return;
}
if(x==curNode->Min||x==curNode->Max) return;
if(x<curNode->Min)
{
std::swap(x,curNode->Min);
}
if(curNode->u>)
{
const int highX=curNode->high(x);
const int lowX=curNode->low(x);
if(GetMinValue(curNode->cluster[highX])==m_inValidValue)
{
insert(curNode->summary,highX);
insertEmptyNode(curNode->cluster[highX],lowX);
}
else
{
insert(curNode->cluster[highX],lowX);
}
}
if(x>curNode->Max) curNode->Max=x;
} void remove(TreeNode* curNode,int x)
{
if(curNode->Min==curNode->Max)
{
curNode->Min=curNode->Max=m_inValidValue;
return;
}
if(curNode->u==)
{
if(x==) curNode->Min=;
else curNode->Min=;
curNode->Max=curNode->Min;
return;
}
if(x==curNode->Min)
{
int firstCluster=GetMinValue(curNode->summary);
x=curNode->index(firstCluster,
GetMinValue(curNode->cluster[firstCluster]));
curNode->Min=x;
} const int highX=curNode->high(x);
const int lowX=curNode->low(x);
remove(curNode->cluster[highX],lowX);
if(GetMinValue(curNode->cluster[highX])==m_inValidValue)
{
remove(curNode->summary,highX);
if(x==curNode->Max)
{
int summaryMax=GetMaxValue(curNode->summary);
if(summaryMax==m_inValidValue) curNode->Max=curNode->Min;
else
{
curNode->Max=curNode->index(summaryMax,
GetMaxValue(curNode->cluster[summaryMax]));
}
}
}
else
{
if(x==curNode->Max)
{
curNode->Max=curNode->index(highX,
GetMaxValue(curNode->cluster[highX]));
}
}
} public: /**
构造函数需要提供类型的无效值
**/
VanEmdeBoasTree(const int inValidValue=-)
{
m_MAXRANGE=MAXU;
m_inValidValue=inValidValue;
m_root=new TreeNode;
build(m_root,MAXU);
} /**
key存在 返回1 否则返回0
**/
int isExist(int key)
{
if(key<||key>=MAXU) return ; TreeNode* curNode=m_root;
while()
{
if(key==curNode->Min||key==curNode->Max) return ;
else if(==curNode->u) return ;
else
{
TreeNode *nextNode=curNode->cluster[curNode->high(key)];
key=curNode->low(key);
curNode=nextNode;
}
}
} /**
查找key的后继 即大于key最小的值
若没有 返回m_inValidValue
**/
int getSuccessor(int key)
{
if(key<) return GetMinValue(m_root);
if(key>=m_MAXRANGE) return m_inValidValue;
return getSuccessor(m_root,key);
} /**
查找key的前驱 即小于key最大的值
若没有 返回m_inValidValue
**/
int getPredecessor(int key)
{
if(key<) return m_inValidValue;
if(key>=m_MAXRANGE) return GetMaxValue(m_root);
return getPredecessor(m_root,key);
} void insert(int key)
{
if(key<||key>=m_MAXRANGE) return;
insert(m_root,key);
} void remove(int key)
{
if(key<||key>=m_MAXRANGE) return;
remove(m_root,key);
} int GetMaxValue()
{
return GetMaxValue(m_root);
} int GetMinValue()
{
return GetMinValue(m_root);
}
};
van Emda Boas的更多相关文章
- BZOJ 3685: 普通van Emde Boas树( 线段树 )
建颗权值线段树就行了...连离散化都不用... 没加读入优化就TLE, 加了就A掉了...而且还快了接近1/4.... ---------------------------------------- ...
- bzoj3685普通van Emde Boas树 线段树
3685: 普通van Emde Boas树 Time Limit: 9 Sec Memory Limit: 128 MBSubmit: 1932 Solved: 626[Submit][Stat ...
- BZOJ_3685_普通van Emde Boas树_权值线段树
BZOJ_3685_普通van Emde Boas树_权值线段树 Description 设计数据结构支持: 1 x 若x不存在,插入x 2 x 若x存在,删除x 3 输出当前最小值,若不存 ...
- Van Emde Boas Tree
van Emde Boas trees 支持所有优先级优先级队列的操作,并且巧妙的是它对于SEARCH, INSERT,DELETE,MINIMUM,MAXMUN,SUCCESSOR,和PREDECE ...
- bzoj 3685: 普通van Emde Boas树
3685: 普通van Emde Boas树 Description 设计数据结构支持:1 x 若x不存在,插入x2 x 若x存在,删除x3 输出当前最小值,若不存在输出-14 输出当 ...
- 【bzoj3685】普通van Emde Boas树 线段树
普通van Emde Boas树 Time Limit: 9 Sec Memory Limit: 128 MBSubmit: 1969 Solved: 639[Submit][Status][Di ...
- 算法导论笔记——第二十章 van Emde Boas树
当关键字是有界范围内的整数时,能够规避Ω(lglgn)下界的限制,那么在类似的场景下,我们应弄清楚o(lgn)时间内是否可以完成优先队列的每个操作.在本章中,我们将看到:van Emde Boas树支 ...
- 浅谈 van Emde Boas 树——从 u 到 log log u 的蜕变
本文参考算法导论完成. 模板题在此 QwQ 优化的过程比较长,还请读者耐心阅读,认真理解. 最初的想法 我会暴力! 用一个 \(size\) 数组维护每个元素出现的次数. 不细讲,时间复杂度 \(O( ...
- BZOJ3685: 普通van Emde Boas树
显然这题的所有操作都可以用set,但是直接用set肯定要T,考虑到读入量较大,使用fread读入优化,就可以卡过去了. #include<bits/stdc++.h> using name ...
随机推荐
- Maven打jar包
<plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactI ...
- 帮初学者改代码——playerc之“练习:求完数问题”(下)
前文链接:帮初学者改代码——playerc之“练习:求完数问题”(上) 再来看看be_ferfect()应该如何改. be_ferfect()函数的功能是判断number是否为完数,同时把因子对写入d ...
- fix org.openqa.selenium.NoSuchWindowException when find element on ie11.
Steps:1.I was able to resolve the issue after adding the site URL under trusted sites of IE. The sam ...
- spring支持的websocket
首发:个人博客 必须说明:这篇博文只用于自己记录,使用spring的websocket支持一定要看官方文档,权威又简明,不推荐看不专业又啰嗦的国产博文. 已尝试了两种方法,当然,不管哪种方法都要先添加 ...
- Python 进阶(五)定制类
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAugAAAF/CAIAAACUs6uhAAAgAElEQVR4nOzdZXubx7ov8PPV9tlrt0 ...
- win8以上系统,设置英文为默认输入法
说明:这里将添加“简体中文(美式键盘)”,也就是英文输入法,并设置为默认输入法. 1.打开控制面板—时钟.语言和区域—语言,点击“添加语言”,选择“英语”—打开,选择“英语(美国)” —添加. 2.选 ...
- 【jqGrid for ASP.NET MVC Documentation】.学习笔记.1.介绍
1 介绍 jqGrid for ASP.NET MVC 是一个服务端组件. 专为MVC 分隔 model ,view , controller 的原则,完全观察者模式 非常快的速度 仅仅很 ...
- jquery 当前链接激活传递参数|div的切换显示
一.链接激活时传递参数 $("a").click(function(){ var obj=$(this).attr("field"); //获取当前field ...
- http协议了解
在web应用中,服务器把网页的HTML代码发送给浏览器,让浏览器显示出来,浏览器和服务器之间的传输协议就是HTTP协议.HTTP是在网络上传输HTML的协议,用于浏览器和服务器之间的通信. 一个网页打 ...
- mini.open打开窗口时传递参数
mini.open({ url: "xxx.html", showMaxButton: false, allowResize: false, title: '标题', width: ...