【清华集训2016】Alice和Bob又在玩游戏
生活随笔
收集整理的這篇文章主要介紹了
【清华集训2016】Alice和Bob又在玩游戏
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
不難的題目。因為SG性質,所以只需要對一棵樹求出。
然后如果發現從上往下DP不太行,所以從下往上DP。
考慮一個點對子樹的合并,考慮下一個刪的點在哪一個子樹,那么剩下的狀態實際上就是把一個子樹所有能達到的狀態異或上一個數。
此時還有不到子樹的狀態,直接插入子樹SG異或值。
所以顯然,就是維護一個支持全部異或,以及狀態合并,查詢mex的數據結構,直接trie合并帶tag就好了。
時空復雜度 \(O(n \log n)\)
#include <bits/stdc++.h>const int MAXN = 100010; const int UP = 21; const int MN = MAXN * (UP + 1); int son[MN][2], val[MN], tag[MN], txt; void mktag(int u, int v) { tag[u] ^= v; } void pushdown(int u, int dig) {if (tag[u]) {if (son[u][0]) mktag(son[u][0], tag[u]);if (son[u][1]) mktag(son[u][1], tag[u]);if (tag[u] >> dig & 1)std::swap(son[u][0], son[u][1]);tag[u] = 0;} } void update(int u) { val[u] = val[son[u][0]] + val[son[u][1]]; } void insert(int & x, int v, int dig = UP) {if (!x) x = ++txt, son[x][0] = son[x][1] = val[x] = tag[x] = 0;if (dig == -1) return (void) (val[x] = 1);pushdown(x, dig);insert(son[x][v >> dig & 1], v, dig - 1);update(x); } int merge(int x, int y, int dig = UP) {if (!x || !y) return x | y;pushdown(x, dig), pushdown(y, dig);son[x][0] = merge(son[x][0], son[y][0], dig - 1);son[x][1] = merge(son[x][1], son[y][1], dig - 1);if (dig != -1) update(x);return x; } int query(int u, int dig = UP) {if (!u) return 0;if (val[son[u][0]] < (1 << dig)) return query(son[u][0], dig - 1);return query(son[u][1], dig - 1) | 1 << dig; } int head[MAXN], nxt[MAXN << 1], to[MAXN << 1], tot; void addedge(int b, int e) {nxt[++tot] = head[b]; to[head[b] = tot] = e;nxt[++tot] = head[e]; to[head[e] = tot] = b; } int sg[MAXN], rts[MAXN]; bool vis[MAXN]; int solve(int u, int fa = 0) {vis[u] = true;int pre = 0, & rt = rts[u];for (int i = head[u]; i; i = nxt[i]) if (to[i] != fa)solve(to[i], u), pre ^= sg[to[i]];for (int i = head[u]; i; i = nxt[i]) if (to[i] != fa) {mktag(rts[to[i]], pre ^ sg[to[i]]);rt = merge(rt, rts[to[i]]);}insert(rt, pre);sg[u] = query(rt);return rt; } int n, m; int main() {std::ios_base::sync_with_stdio(false), std::cin.tie(0);int T; std::cin >> T;while (T --> 0) {std::cin >> n >> m;for (int i = 1; i <= m; ++i) {int t1, t2; std::cin >> t1 >> t2;addedge(t1, t2);}int ans = 0;for (int i = 1; i <= n; ++i) if (!vis[i])solve(i), ans ^= sg[i];std::cout << (ans ? "Alice" : "Bob") << '\n';tot = 0; memset(head, 0, n + 1 << 2);memset(vis, 0, n + 1); txt = 0;memset(rts, 0, n + 1 << 2);}return 0; }轉載于:https://www.cnblogs.com/daklqw/p/11563341.html
總結
以上是生活随笔為你收集整理的【清华集训2016】Alice和Bob又在玩游戏的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: b站编程课程资源汇总
- 下一篇: 心得体悟帖---14、没有自己精品项目永