专栏文章

CF1481F

CF1481F题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miqbgvx0
此快照首次捕获于
2025/12/04 02:04
3 个月前
此快照最后确认于
2025/12/04 02:04
3 个月前
查看原文
本题解仅为一种线性空间做法的介绍。其他部分不再赘述。
其实就是一个小技巧:线性空间记录 bool 背包每个大小的转移是放入了什么物品。关键在于,注意到对于每个背包大小 xx,我们只需要在 dpi,xdp_{i,x} 第一次为 11 时记录这次转移中放入了什么就行。
这样构造的正确性也相当显然。设上述大小为 xx 的背包,放入的物品为 fif_i。假设 dpi,xdp_{i,x} 是从 dpi1,ydp_{i-1,y} 转移过来,那么在更新 fxf_xfyf_y 一定有值,并且以后不再修改。同时 fxf_x 显然比 fyf_y 更晚放入背包,所以构造时依次取出的物品不会重复,方案合法。
其实主要还是自己想想才好理解。
然后这个东西也厉害在它可能兼容 bitset 优化 bool 背包。具体地,你只需要将 dpidp_idpi1dp_{i-1} 的 bitset 异或一下就能得到在 dpi,xdp_{i,x} 第一次为 11xx,然后记录 fxf_x。由于这样的 xx 总共不超过 sizsiz 个,所以配合 _Find_next 相关操作,这一部分总复杂度为 O(siz)O(siz),大部分情况下可以接受。
code:
CPP
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();
	}
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...