快来踩爆这个蒟蒻吧|

Little_corn

园龄:1年1个月粉丝:10关注:17

2024-04-25 13:21阅读: 21评论: 0推荐: 0

CF1709E XOR Tree

link

Solution:

PART 1: 转化

首先套路地预处理出每个节点到根节点(1 号节点)路径上的点权异或和 w[u]

可以发现题意容易转化为:给定一棵 n 个节点的树,问你最少可以把它分成多少个联通块,使得每个连通块中的节点两两路径上的异或和不为 0

易知对于一个节点,若它要被割分出原来的树,那么一定是在它的子树中有两个点对 (x,y) 没有割分出原树且 w[x] xor w[y] xor a[LCA(x,y)]=0

PRAT 2:暴力

考虑朴素做法:对每个节点开一个 set 记录每个节点子树中没有被割分出去的所有节点的 w 值。枚举 LCA(x,y)(令它为 u),如果对于节点 u 的儿子节点 v,可以在 uset 中找到一个节点 t,使得 w[t] xor w[v] xor a[u]=0 。那么就一定要将点 u 割分出去。

具体来讲,我们暴力的合并节点 u 的所有儿子的 set,并且枚举其中的点 t ,若可以在 vset 中找到一个节点 t ,使得 w[t] xor w[v] xor a[u]=0,那么清空 uset,并使答案加一

此时的最坏时间复杂度会在树是一个链的情况下退化成 O(n2logn)

PART 3:优化

钦定 son[u]u 的所有子节点中子树大小最大的一个,称为重儿子,其他称为轻儿子。可以发现若朴素的合并所有轻儿子,并以 O(1) 的时间复杂度合并重儿子,那么每个节点至多被朴素合并 O(logn) 次。

因此我们对于重儿子直接使用 O(1)swap 交换 uson[u]set ,并只查询 w[u] xor a[u] 是否在 set 中出现,此时相当于合并了。对于轻儿子,直接进行暴力的合并。

这种技巧被我们称作 dsu on tree (树上启发式合并)

时间复杂度降为 O(nlog2n)

code:

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
vector<int>G[N];
set<int>S[N];
int n, a[N], s[N], siz[N], son[N], ans;
void dfs(int u, int fa){
siz[u] = 1;
s[u] = a[u] ^ s[fa];
for(auto v:G[u]){
if(v == fa)continue;
dfs(v, u);
if(siz[v] > siz[son[u]]) son[u] = v;
siz[u] += siz[v];
}
return;
}
void dsu(int u, int fa){
bool res = 0;
if(son[u]){
dsu(son[u], u);
if(S[son[u]].find(s[u] ^ a[u]) != S[son[u]].end()) res = 1;
swap(S[u], S[son[u]]);
}
S[u].insert(s[u]);
for(auto v:G[u]){
if(v != fa && v != son[u]){
dsu(v, u);
for(auto t:S[v]) if(S[u].find(t ^ a[u]) != S[u].end()) res = 1;
for(auto t:S[v]) S[u].insert(t);
}
}
if(res){
//cout << u << " " << res << "\n";
ans++;
S[u].clear();
}
return;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> n;
for(int i = 1; i <= n; i++)cin >> a[i];
for(int i = 1; i < n; i++){
int x, y;
cin >> x >> y;
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1, 0);
dsu(1, 0);
cout << ans;
return 0;
}

本文作者:Little_corn

本文链接:https://www.cnblogs.com/little-corn/p/18157504

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Little_corn  阅读(21)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起