CodeForces 1709E XOR Tree
思路
令 为根,并设 为 到 的路径上经过的点的异或和,则 两点路径经过点的异或和可以转化成 。
因为题目没有限制,所以可以将点权修改为奇奇怪怪的值,保证 不同子树内没有两点异或和为 。
对每一个点开一个 set
表示当前子树的所有 ,每次对于子结点启发式合并,遍历 的 set
内的元素,设当前遍历到元素 ,找 的 set
存不存在 。若存在就说明 必须要修改。修改后 的 set
可以清零,意味着不用再考虑。
时间复杂度 。
代码
code
/* p_b_p_b txdy AThousandSuns txdy Wu_Ren txdy Appleblue17 txdy */ #include <bits/stdc++.h> #define pb push_back #define fst first #define scd second #define mems(a, x) memset((a), (x), sizeof(a)) using namespace std; typedef long long ll; typedef unsigned long long ull; typedef long double ldb; typedef pair<ll, ll> pii; const int maxn = 200100; int n, a[maxn], head[maxn], len, ans; set<int> st[maxn]; struct edge { int to, next; } edges[maxn << 1]; void add_edge(int u, int v) { edges[++len].to = v; edges[len].next = head[u]; head[u] = len; } void dfs(int u, int fa, int d) { bool flag = 0; st[u].insert(d); for (int i = head[u]; i; i = edges[i].next) { int v = edges[i].to; if (v == fa) { continue; } dfs(v, u, d ^ a[v]); if ((int)st[v].size() > (int)st[u].size()) { swap(st[u], st[v]); } if (!flag) { for (int x : st[v]) { if (st[u].find(x ^ a[u]) != st[u].end()) { flag = 1; ++ans; break; } } } for (int x : st[v]) { st[u].insert(x); } st[v].clear(); } if (flag) { st[u].clear(); } } void solve() { scanf("%d", &n); for (int i = 1; i <= n; ++i) { scanf("%d", &a[i]); } for (int i = 1, u, v; i < n; ++i) { scanf("%d%d", &u, &v); add_edge(u, v); add_edge(v, u); } dfs(1, -1, a[1]); printf("%d\n", ans); } int main() { int T = 1; // scanf("%d", &T); while (T--) { solve(); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现