bzoj3685普通VEB树

这是一种来自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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值