问一下这个二叉堆任意元素删除函数哪里有问题,数据量大了就不满足堆性质了。
  • 板块P1484 种树
  • 楼主risingstar
  • 当前回复2
  • 已保存回复2
  • 发布时间2021/1/3 13:57
  • 上次更新2023/11/5 05:12:31
查看原帖
问一下这个二叉堆任意元素删除函数哪里有问题,数据量大了就不满足堆性质了。
397949
risingstar楼主2021/1/3 13:57

如题,代码如下:

#include<stdio.h> 
#define max(a,b) (a>b?a:b)
int rk[500010];/*若为区间端点则保存对应节点在堆中下标*/
struct T{
	long long v;//节点值
	int lid;//每个节点对应左端点
	int rid;//每个节点对应右端点
	int siz;//选择该节点种的树的棵树
};
struct T t[500010];
void maxheapify(int o,int m)
{
	int l=o<<1;
	int r=o<<1|1;
	int ind=o;
	if(l<=m&&t[l].v>t[ind].v)ind=l;
	if(r<=m&&t[r].v>t[ind].v)ind=r;
	if(ind!=o){
		rk[t[ind].lid]=rk[t[ind].rid]=o;
		rk[t[o].lid]=rk[t[o].rid]=ind;
		struct T tt=t[o];
		t[o]=t[ind];
		t[ind]=tt;
		maxheapify(ind,m);
	}
}
void update(int o)
{
	int f=o>>1;
	if(f>=1&&t[f].v<t[o].v){
		rk[t[f].lid]=rk[t[f].rid]=o;
		rk[t[o].lid]=rk[t[o].rid]=f;
		struct T tt=t[o];
		t[o]=t[f];
		t[f]=tt;
		update(o);
	}
}
int del(int o,int m)
{
	if(o==m)return m-1;
	if(t[o].v>t[m].v){
		t[o]=t[m];
		rk[t[m].lid]=rk[t[m].rid]=o;
		maxheapify(o,--m);
	}
	else{
		t[o]=t[m];
		rk[t[m].lid]=rk[t[m].rid]=o;
		update(o);
		--m;
	}
	return m;
} 
int main()
{
	//freopen("P1484_4.in","r",stdin);
	int n,k;
	int m;
	scanf("%d%d",&n,&k);
	m=n;
	for(int i=1;i<=n;i++){
		rk[i]=t[i].lid=t[i].rid=i;
		scanf("%lld",&t[i].v);
		t[i].siz=1;
	}
	for(int i=m>>1;i>=1;i--){
		maxheapify(i,m);
	}
	long long ans=0,num=0,tans=0;
	struct T tt1,tt2;
	while(1){
		if(m<=1)break;
		ans+=t[1].v;
		num+=t[1].siz;
		if(num<=k)tans=max(ans,tans);
		if(t[1].lid-1>=1){
			tt1=t[rk[t[1].lid-1]];
			m=del(rk[t[1].lid-1],m);
		}
		else tt1=t[0];
		if(t[1].rid+1<=n){
			tt2=t[rk[t[1].rid+1]];
			m=del(rk[t[1].rid+1],m);
		}
		else tt2=t[0];
		t[1].siz*=-1;
		t[1].v*=-1;
		if(tt1.lid){
			t[1].siz+=tt1.siz;
			t[1].v+=tt1.v;
			t[1].lid=tt1.lid;
			rk[t[1].lid]=1;
		}
		if(tt2.lid){
			t[1].siz+=tt2.siz;
			t[1].v+=tt2.v;
			t[1].rid=tt2.rid;
			rk[t[1].rid]=1;
		}
		maxheapify(1,m);
	}
	printf("%lld",tans);
}
2021/1/3 13:57
加载中...