CS 400 Path Union 思维+贪心

题意:高度为n的满二叉树,若一个节点u被选择,则u到root的边变成黑色
长度为n的序列a, a[i]表示树的第i层最多可以选a[i]个节点.
1<=n<=60, 0<=a[i]<2^i   序列a之和<=1e5. 问应该选择那些点 使得黑色的边最多?


考虑一颗满二叉树 只选叶子节点的情况.
假如只选1个 则任意 选两个 则显然出前一半和后一半中各自任选一个.
假如只选4个,则每个1/4为一块各自任选一个.....


对每一层都做上面的贪心操作.
若选了节点u 则在选u得祖先没有意义不会增加任何黑边.
假如当前层要选a[i]个 则实际上儿子已经帮该层选了(a[i+1],a[i+2]+...a[n])个点.现在总共要选suf[i]个点.

输出最后a[i]个点即为这一层选的点.

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,a[N];
vector<ll> solve(ll n,ll sz)
{
	vector<ll> res;
	n=1ll<<n;
	sz=min(sz,n);
	if(sz==0)
		return	res;
	res.push_back(0);
	if(sz==1)
		return res;
	res.push_back(n/2);
	if(sz==2)
		return res;
	ll p=n/4,add=n/2;
	while((ll)res.size()<sz)
	{
		res.push_back(p);
		p+=add;
		if(p>n)
			p=add/4,add/=2;
	}
	return res;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++)
		cin>>a[i];
	for(int i=n;i>=1;i--)
	{
		vector<ll> v=solve(i,a[i]+a[i+1]);
		for(int j=a[i+1];j<v.size();j++)
			cout<<(1ll<<i)+v[j]<<endl;
		a[i]+=a[i+1];
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值