CF1709E XOR Tree
Solution:
PART 1: 转化
首先套路地预处理出每个节点到根节点(
可以发现题意容易转化为:给定一棵
易知对于一个节点,若它要被割分出原来的树,那么一定是在它的子树中有两个点对
PRAT 2:暴力
考虑朴素做法:对每个节点开一个
具体来讲,我们暴力的合并节点
此时的最坏时间复杂度会在树是一个链的情况下退化成
PART 3:优化
钦定
因此我们对于重儿子直接使用
这种技巧被我们称作
时间复杂度降为
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 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步