爆零小技巧合集【施工中】
#1
请观察
void mul(ll a[N][N],ll b[N],ll c[N]){
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
c[i]+=a[i][j]*b[j];c[i]%=mod;
}
}
}
有什么问题吗?问题出在 \(memset\) 上,这个函数传数组默认都是传指针的,所以 \(sizeof(c)\) 得到的是指针的长度,也就是 \(8\)
#2
这是个 \(FHQ\_Treap\) ,请观察:
int rank(int i,int num){
//查找几个数比num小
if(num==val[i]){
return size[left[i]];
}
if(num<val[i])
return rank(left[i],num);
return size[left[i]]+count[i]+rank(right[i],num);
}
是的,没写递归边界, \(TLE\) 了
#3
与上面是同一份代码,还是 \(FHQ\_Treap\) ,不过与算法本身没啥关系,请观察:
void query(int i,int num,int ord,int &ans){
if(i==0) return;
if(ord==1){//1取前驱
if(val[i]<num){
ans=std::max(ans,val[i]);
query(right[i],num,ord,ans);
}
else query(left[i],num,ord,ans);
}
else if(ord==2){
if(val[i]>num){
ans=std::min(ans,val[i]);
query(left[i],num,ord,ans);
}
else query(right[i],num,ord,ans);
}
}
int getpre(int num){
int ret=-1;
query(head,num,1,ret);
return ret;
}
int getnext(int num){
int ret=INT_MAX;
query(head,num,2,ret);
return ret;
}
是的,将 \(val[i]\) 错用为 \(ord\) 了。
#4
又又又是同一份代码,请观察:
void update(int i){
size[i]=count[i]+size[left[i]]+size[right[i]];
}
void changeCount(int i,int change){
count[i]+=change;
}
void New(int num){
val[++tot]=num;
count[tot]=size[tot]=1;
priority[tot]=rand()%1000;//随机分配优先级
}
void add(int num){
if(tot==0){
New(num);
head=1;
return;
}
int pos=find(head,num);
if(pos!=0){
changeCount(pos,1);
}
else{
split(0,0,head,num);
New(num);
head=merge(merge(right[0],tot),left[0]);
}
}
是的,直接修改单点值,导致祖先节点信息没能正确合并。

浙公网安备 33010602011771号