哈夫曼树

贪心合并,第一关键字为子树权值。为了让最大的能够尽量完全合并,所以最开始要合并一些小的,即 \([1,n-((n-1)/(k-1)*(k-1))]\)。然后每次合并 \(k\) 个。如果需要让深度最小就在排序的时候设第二关键字为当前子树深度从小到大。
然后如果是求 \(n\) 个不同的 \(k\) 的答案可以 \(n\log n\) 做,就是做到 \(\frac n 2+\frac n 3+\cdots\) 为此需要把原数组排序,取前缀和,然后队列里只存合并出的值,每次从 \(e=s+k-1\) 开始往前看需不需要把 \(e\) 换成 \(q.top()\)。换到最后还需要把队列里的合并完。
具体代码

点击查看代码
priority_queue<int>q;
int solve(int k){
	int res=0,ans=0,s=1,e=n-((n-1)/(k-1)*(k-1));
	if(e>s) ans+=sum[e],q.push(-sum[e]),s=e+1;
	while(s<n+q.size()){
		e=s+k-1,res=0;
		while(!q.empty()&&s<=e&&(e>n||-q.top()<sum[e]-sum[e-1]))
			res+=-q.top(),q.pop(),e--;
		res+=sum[e]-sum[s-1];
		q.push(-res),s=e+1,ans+=res;
	}
	while(!q.empty())q.pop();
	return ans;	
}

例题WOJ4660

posted @ 2022-02-16 10:45  llmmkk  阅读(64)  评论(0)    收藏  举报