题意:高度为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]个点.
长度为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;
}