题解:P9809 [SHOI2006] 作业 Homework
OrientDragon · · 题解
提供一个理论上写起来比较快的代码。
首先设置阈值
当
我们设
对于 std::set 的维护可能是平凡的,但我们可以三层分块一下,这样我们的查询
附上查询后继的方式:
u64 L0[4692],L1[76],L2[4];
inline void insert(u32 x){
L0[x>>6]|=1ull<<(x&63);
L1[x>>12]|=1ull<<((x>>6)&63);
L2[x>>18]|=1ull<<((x>>12)&63);
}
inline u32 nxt(u32 x){
if(x>M)return inf;
u32 i0=x>>6,b0=x&63;
if(u64 w=L0[i0]&(~0ull<<b0))return(i0<<6)|countr_zero(w);
u32 i1=(i0+1)>>6,b1=(i0+1)&63;
if(u64 w=L1[i1]&(~0ull<<b1)){
u32 n1=(i1<<6)|countr_zero(w);
return(n1<<6)|countr_zero(L0[n1]);
}
u32 i2=(i1+1)>>6,b2=(i1+1)&63;
if(u64 w=L2[i2]&(~0ull<<b2)){
u32 n2=(i2<<6)|countr_zero(w);
u32 n1=(n2<<6)|countr_zero(L1[n2]);
return(n1<<6)|countr_zero(L0[n1]);
}
return inf;
}