题解: CF1824C(LuoTianyi and XOR-Tree)
1. Description
给定一棵 \(n\) 个节点的树,根节点为 \(1\),每个点有一个点权 \(a_i\),每次操作可以选择一个点任意修改点权,求最少的操作次数,使得每一条根结点到叶子结点的路径上的异或和都为 \(0\)。
2. Solution
我果然理解不了锦依卫们的思路
此时不妨设 \(val(u,v)\) 表示 \(u\) 到 \(v\) 的路径上,所有点点权的异或和,\(leaf_u\) 表示以 \(u\) 为根的子树中,所有叶子结点的编号构成的集合,\(son_u\) 表示 \(u\) 的所有子节点构成的集合。
此时我们考虑一个树形 DP,定义 \(f_{u,x}\) 表示使得 \(\forall v\in leaf_y,val(v,u)=x\) 的操作次数最小值,那么 \(f_{u,x}={\min\limits_{i=1}^V([i\ne x]+\sum_{v\in son_u}f_{v,i})}\),这样就可以得到时间复杂度为 \(O(nV)\) 的做法。
而显然有这样一个结论:当以 \(u\) 为根的子树中,满足 \(\forall v\in lead_u,val(v,u)\) 均相等,那么我们可以通过更改 \(u\) 的点权,使得所有 \(val(v,u)\) 变成任意一个我们想要的值。
这个结论带来的结果就是如果我们记 \(mi=\min\limits_{i=1}^V \{f_{u,x}\}\),那么对于任意的 \(x\in [1,V]\),\(f_{u,x}\in \{mi,mi+1\}\)。
这个结果很有意思,对于一个节点,我们只需要记录 \(mi,S\),用来表示使得 \(\forall v\in lead_u,val(v,u)\) 均相等的操作次数,和在这样的限制下可以达到的相同的值的集合,就可以表示这个点的 \(dp\) 值,而这样,我们的转移就变得简单了起来。
这个时候记录 \(cnt_x\) 表示 \(x\) 这个值在 \(S_v,v\in son_u\) 中出现了几次,\(mx=\max\limits_{i=1}^V (cnt_i)\),那么 \(mi_u=|son_u|-mx+\sum_{v\in son_u} mi_v\)。
这样,我们就可以用启发式合并来维护 \(mi_u\) 和 \(S_u\) 了。
最后统计答案,只需要看看 \(S_1\) 中有没有 \(0\),如果有,那么答案为 \(mi_1\),否则,答案为 \(mi_1+1\)。
3. Code
/*by qwer6*/
/*略去快读快写与缺省源*/
const int N=1e5+5;
int n;
int siz[N],son[N],bel[N],val[N],tag[N],f[N];
bool leaf[N];
unordered_map<int,int>cnt;
set<int>st[N],now;
vector<int>e[N];
void dfs(int u,int fa){
siz[u]=1;
for(int v:e[u]){
if(v==fa)continue;
dfs(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
if(siz[u]==1)leaf[u]=1;
}
void redfs(int u,int fa){
if(leaf[u]){
bel[u]=u;
tag[u]=val[u];
st[u].insert(0);
return ;
}
int cntson=0;
for(int v:e[u]){
if(v==fa)continue;
cntson++;
redfs(v,u);
f[u]+=f[v];
}
if(cntson==1){
bel[u]=bel[son[u]],tag[u]=tag[son[u]]^val[u];
return ;
}
cnt.clear();
now.clear();
int mx=0,idx,tmp;
for(int v:e[u]){
if(v==fa||v==son[u])continue;
idx=bel[v];
for(int x:st[idx]){
tmp=x^tag[v];
if(now.count(tmp))cnt[tmp]++;
else{
now.insert(tmp);
cnt[tmp]=1;
}
tomax(mx,cnt[tmp]);
}
st[idx].clear();
}
idx=bel[son[u]];
for(int x:now){
tmp=x^tag[son[u]];
if(st[idx].count(tmp)){
cnt[x]++;
tomax(mx,cnt[x]);
}
}
f[u]+=cntson-mx;
if(mx>1){
bel[u]=u,tag[u]=val[u];
for(int x:now)
if(cnt[x]==mx)st[u].insert(x);
}else{
bel[u]=bel[son[u]],tag[u]=tag[son[u]]^val[u];
for(int x:now)st[bel[u]].insert(x^tag[son[u]]);
}
}
signed main(){
read(n);
for(int i=1;i<=n;i++)read(val[i]);
for(int i=2,u,v;i<=n;i++){
read(u),read(v);
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1,0);
redfs(1,0);
if(st[bel[1]].count(tag[1]))write(f[1]);
else write(f[1]+1);
}

浙公网安备 33010602011771号