题意为让我们建一棵树,并为每个节点分配权值,在该节点建防御塔会花费ci的金钱
每个叶节点会诞生怪物,并开始沿着路径向根节点走,你要有k种花费最少的金钱建造防御塔的方案,使得所有怪物都被防御塔阻拦
输出设计的这棵树和每个点的权值
我们可以借助二进制拼凑的思想
因为一个数是一定可以拆成
加起来的
所以我们可以构造一颗这样的树
图中每一个阴影分支可以有
的贡献,而对于每一个
,如果需要它,它就可以提供
的贡献(只要让他的c值等于以他为根子树叶节点c值之和,他就可以提供贡献)
这样我们就可以用二进制拼凑拼出任意的
例如我们要拼出
可以看到
提供了
的贡献
而
号节点和
号节点,都等于以他为根的子树叶节点权值和,所以
分别提供
的贡献
答案为8+2+1=11
代码如下:
用dfs实现,每一层向右建一个2的子树,向左递归k/2
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+10;
int p[N];
int c[N];
int sum;
int tmp[N];
signed main(){
int k;
cin>>k;
function<int(int,int)> dfs=[&](int k,int fa){
int now=++sum;
p[now]=fa;
if(k<=2){
p[++sum]=now;
c[sum]=1;
tmp[now]=1;
c[now]=3-k;
return 1ll;
}
tmp[now]+=dfs(k/2,now);
tmp[now]+=dfs(2,now);
c[now]=tmp[now]+(k%2==0);
return tmp[now];
};
dfs(k,0);
cout<<sum<<'\n';
for(int i=2;i<=sum;++i){
cout<<p[i]<<" ";
}
cout<<endl;
for(int i=1;i<=sum;++i){
cout<<c[i]<<" ";
}
}