这是一种来自xehoth大爷的奇技淫巧
我改造了一下,从
23
叉7层改成
24
叉5层,以适应
220
左右的值域,但这可能缓存不优?因为辅助数组长度为65536,可能装不进缓存,感觉不太懂这套理论。
把5层改成6层(值域变成16777216)后测了一下:
插入
107
个随机数是870ms左右;
删除
107
个随机数是335ms左右(因为随出来的不一定在集合里)
查
107
次最值240ms左右
查
107
次前驱后继差不多200ms都一点(因为插入的数密集之后)
可见这种数据结构即使值域很大,
107
一样随便跑,效果跟loglog的埃氏筛差不多(可能略差?)。
如果追求效率,值域远大于操作数时还可以基排离散化
实际评测时间都耗在IO和初始化上了
Orz wangyisong,xllend3
#include<cstdio>
#include<cctype>
inline char read() {
static const int IN_LEN = 10000000;
static char buf[IN_LEN], *s, *t;
if (s == t) {
t = (s = buf) + fread(buf, 1, IN_LEN, stdin);
if (s == t) return -1;
}
return *s++;
}
template<class T>
inline void read(T &x) {
static char c;
static bool iosig;
for (c = read(), iosig = false; !isdigit(c); c = read()) {
if (c == -1) return;
if (c == '-') iosig = true;
}
for (x = 0; isdigit(c); c = read())
x = (x + (x << 2) << 1) + (c ^ '0');
if (iosig) x = -x;
}
const int OUT_LEN = 1000000;
char obuf[OUT_LEN], *oh = obuf;
inline void print(char c) {
if (oh == obuf + OUT_LEN) fwrite(obuf, 1, OUT_LEN, stdout), oh = obuf;
*oh++ = c;
}
template<class T>
inline void print(T x) {
static int buf[30], cnt;
if (x == 0) {
print('0');
} else {
if (x < 0) print('-'), x = -x;
for (cnt = 0; x; x /= 10) buf[++cnt] = x % 10 + 48;
while (cnt) print((char)buf[cnt--]);
}
}
inline void flush() {
fwrite(obuf, 1, oh - obuf, stdout);
}
struct RVEBT{
static const int A=65539,B=1050005;
bool b[1000005];
unsigned int lc[17],rc[17],lb[A],rb[A];
unsigned short v[6][B];
inline void init(){
register int i,j;
for(i=0;i<16;++i){
for(j=0;j<1<<i;++j)
rb[1<<i|j]=i;
for(j=0;j<1<<(15-i);++j)
lb[1<<i|j<<i+1]=i;
}
for(i=0;i<16;++i)lc[i]=65535>>16-i,rc[i]=65535&(65535<<i+1);
}
inline void insert(register int x){
if(!b[x])
for(register int i=b[x]=1;i<6;++i,x>>=4)
v[i][x>>4]|=1<<(x&15);
}
inline void erase(register int x){
if(b[x]){b[x]=0;
for(register int i=1;i<6;x>>=4)
if(v[i++][x>>4]^=1<<(x&15))return;};
}
inline int min(){
if(!v[5][0])return -1;
register int i=4,p=lb[v[5][0]];
for(;i;)p=p<<4|lb[v[i--][p&65535]];
return p;
}
inline int max(){
if(!v[5][0])return -1;
register int i=4,p=rb[v[5][0]];
for(;i;)p=p<<4|rb[v[i--][p&65535]];
return p;
}
inline int prec(register int x){
if(!v[5][0])return -1;
register int i=2,s=v[1][x>>4]&lc[x&15];
if(s)return x>>4<<4|rb[s];
for(;x>>=4,i<6;++i){
s=v[i][x>>4]&lc[x&15];
if(s){
x=x>>4<<4|rb[s];
for(register int j=i-1;j;)
x=(x<<4)|rb[v[j--][x]];
return x;
}
}
return -1;
}
inline int succ(register int x){
if(!v[5][0])return -1;
register int i=2,s=v[1][x>>4]&rc[x&15];
if(s)return x>>4<<4|lb[s];
for(;x>>=4,i<6;++i){
s=v[i][x>>4]&rc[x&15];
if(s){
x=x>>4<<4|lb[s];
for(register int j=i-1;j;)
x=(x<<4)|lb[v[j--][x]];
return x;
}
}
return -1;
}
}t;
int n,m,o,x;
int main(){
t.init();
read(n);
read(m);
while(m--){
read(o);
if(o<3 || 4<o)read(x);
if(o&1){
if(o&2){
if(o&4){
if(!t.b[x])print('-');
print('1');
}else print(t.min());
}else if(o&4)print(t.prec(x));
else t.insert(x);
}else if(o&2){
if(o&4)print(t.succ(x));
else t.erase(x);
}else print(t.max());
if(o>2)print('\n');
}
flush();
return 0;
}