CF1481F
本题解仅为一种线性空间做法的介绍。其他部分不再赘述。
其实就是一个小技巧:线性空间记录 bool 背包每个大小的转移是放入了什么物品。关键在于,注意到对于每个背包大小
这样构造的正确性也相当显然。设上述大小为
其实主要还是自己想想才好理解。
然后这个东西也厉害在它可能兼容 bitset 优化 bool 背包。具体地,你只需要将
code:
int n,m,dep[N];
pii frm[N];
bool dp[N],ans[N];
vector<int> f[N],g[N],h[N];
int tot,head[N];
struct node{
int to,nxt;
}e[N];
il void add(int u,int v){
e[++tot]={v,head[u]},head[u]=tot;
}
void dfs(int u,int f){
dep[u]=dep[f]+1;
if(head[u]){
g[dep[u]].eb(u);
}else{
h[dep[u]].eb(u);
}
go(i,u){
int v=e[i].to;
dfs(v,u);
}
}
void Yorushika(){
read(n,m);
rep(i,2,n){
int u;read(u);
add(u,i);
}
dfs(1,0);
rep(i,1,n){
f[g[i].size()+h[i].size()].eb(i);
}
dp[0]=1;
rep(i,1,n){
if(f[i].size()){
int t=f[i].size();
for(int j=1;j<=t;t-=j,j<<=1){
drep(k,n,j*i){
dp[k]|=dp[k-j*i];
}
rep(k,1,n){
if(!frm[k].fi&&dp[k]){
frm[k]=Mp(i,j);
}
}
}
if(t){
drep(k,n,t*i){
dp[k]|=dp[k-t*i];
}
rep(k,1,n){
if(!frm[k].fi&&dp[k]){
frm[k]=Mp(i,t);
}
}
}
}
}
int mx=0;
rep(i,1,n){
mx=max(mx,dep[i]);
}
if(dp[m]){
printf("%d\n",mx);
int u=m;
while(u){
auto [x,y]=frm[u];
rep(_,1,y){
if(!f[x].size()){
break;
}
ans[f[x].back()]=1;
f[x].pop_back();
}
u-=x*y;
}
rep(i,1,n){
pc('a'+!ans[dep[i]]);
}
}else{
printf("%d\n",mx+1);
bool fl=0;
int x=m,y=n-x;
rep(i,1,n){
if(g[i].size()>x){
swap(x,y),fl^=1;
}
for(int j:g[i]){
ans[j]=fl;
x--;
}
for(int j:h[i]){
if(!x){
swap(x,y),fl^=1;
}
ans[j]=fl;
x--;
}
}
rep(i,1,n){
pc('a'+ans[i]);
}
}
}
signed main(){
int t=1;
//read(t);
while(t--){
Yorushika();
}
}