如果你 58 pts WA on #7~12,那大概率是你的前后缀查询出错了。
由于使用了懒删除,所以不能直接套用类似 Splay 的查询方式,因为你可能查到一个空的右儿子,导致结果为右儿子上方的实节点而非右儿子的左子树内的实节点。
如以下情况:
根为 1
1 的右儿子为 3
3 的左儿子为 2
3 为空节点
那么根据某种 Splay 查前继的方式,如果此时查 4 的前继,将会查到 1 而非 2。
错误代码:
int pre(int x,int v,int p){
if(x==0)return p;
if(v<=val[x])return pre(ls[x],v,p);
if(cnt[x]>=1)p=x;
return pre(rs[x],v,p);
}
int suf(int x,int v,int s){
if(x==0)return s;
if(v>=val[x])return suf(rs[x],v,s);
if(cnt[x]>=1)s=x;
return suf(ls[x],v,s);
}
正确代码:
int pre(int v){
return find(rt,rnk(rt,v));
}
int suf(int v){
return find(rt,rnk(rt,v+1)+1);
}
当然,你也可以通过自己的神秘方式去正常查询,但显然不如直接套函数方便。