【清华集训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;
}
【清华集训2016】Alice和Bob又在玩游戏的更多相关文章
- uoj266[清华集训2016]Alice和Bob又在玩游戏(SG函数)
uoj266[清华集训2016]Alice和Bob又在玩游戏(SG函数) uoj 题解时间 考虑如何求出每棵树(子树)的 $ SG $ . 众所周知一个状态的 $ SG $ 是其后继的 $ mex $ ...
- UOJ #266 【清华集训2016】 Alice和Bob又在玩游戏
题目链接:Alice和Bob又在玩游戏 这道题就是一个很显然的公平游戏. 首先\(O(n^2)\)的算法非常好写.暴力枚举每个后继计算\(mex\)即可.注意计算后继的时候可以直接从父亲转移过来,没必 ...
- [UOJ266]Alice和Bob又在玩游戏
[UOJ266]Alice和Bob又在玩游戏 Tags:题解 作业部落 评论地址 TAG:博弈 题意 不同于树的删边游戏,删掉一个点删去的是到根的路径 题解 这题只和计算\(SG\)有关,博弈的有关内 ...
- [BZOJ4730][清华集训2016][UOJ266] Alice和Bob又在玩游戏
题意:俩智障又在玩游戏.规则如下: 给定n个点,m条无向边(m<=n-1),保证无环,对于每一个联通块,编号最小的为它们的根(也就是形成了一片这样的森林),每次可以选择一个点,将其本身与其祖先全 ...
- bzoj4730: Alice和Bob又在玩游戏
Description Alice和Bob在玩游戏.有n个节点,m条边(0<=m<=n-1),构成若干棵有根树,每棵树的根节点是该连通块内编号最 小的点.Alice和Bob轮流操作,每回合 ...
- UOJ#266. 【清华集训2016】Alice和Bob又在玩游戏 博弈,DSU on Tree,Trie
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ266.html 题解 首先我们可以直接暴力 $O(n^2)$ 用 sg 函数来算答案. 对于一个树就是枚举 ...
- uoj#266. 【清华集训2016】Alice和Bob又在玩游戏(博弈论)
传送门 完了我连sg函数是个啥都快忘了 设\(sg[u]\)为以\(u\)为根节点的子树的\(sg\)函数值,\(rem[u]\)表示\(u\)到根节点的路径删掉之后剩下的游戏的异或值 根节点\(u\ ...
- UOJ 266 - 【清华集训2016】Alice和Bob又在玩游戏(SG 定理+01-trie)
题面传送门 神仙题. 首先注意到此题的游戏是一个 ICG,故考虑使用 SG 定理解决这个题,显然我们只需对每个连通块计算一遍其 SG 值异或起来检验是否非零即可.注意到我们每删除一个点到根节点的路径后 ...
- 【bzoj4730】 Alice和Bob又在玩游戏
http://www.lydsy.com/JudgeOnline/problem.php?id=4730 (题目链接) 题意 给出一个森林,两个人轮流操作,每次把一个节点以及它的祖先全部抹去,无节点可 ...
随机推荐
- windows下命令行利器---Cmder(安装,中文乱码,配置右键菜单)
很多人都是在win下开发的,这样就会出现,经常需要命令行操作,而win cmd命令和linux命令有很大差异,导致大家很难受,今天给大家介绍一个win下命令行的利器-Cmder 一.先看一下它的容颜 ...
- java-selenium-java鼠标键盘操作Actions类和Robot
Actions类 一.鼠标右击.双击 Java代码 //定位百度首页右上角 新闻 WebElement Xw=driver.findElement(By.xpath("//*[@id='u1 ...
- Hadoop单机模式/伪分布式模式/完全分布式模式
一.Hadoop的三种运行模式(启动模式) 一.单机(非分布式)模式 这种模式在一台单机上运行,没有分布式文件系统,而是直接读写本地操作系统的文件系统. 默认情况下,Hadoop即处于该模式,用于开发 ...
- redis 学习(12)-- redis 发布订阅
redis 发布订阅 发布订阅模式中的角色 发布者(publisher) 订阅者(subscriber) 频道(channel) 如图所示: 发布者发布消息到频道,订阅了频道的订阅者可以收到消息,订阅 ...
- redis 学习(6)-- 集合类型
redis 学习(6)-- 集合类型 set 结构 无序 无重复 集合间操作 set 集合内操作 命令 含义 sadd key memebr1 [member2...] 向集合中添加一个或多个成员 s ...
- Linux scp命令详解(服务器之间复制文件或目录)
scp:服务器之间复制文件或目录 一.命令格式: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file] [-l limit] ...
- JS定时器的用法及示例
JS定时器的用法及示例 目录 js 定时器的四个方法 示例一 示例二 示例三 js 定时器的四个方法 setInterval() :按照指定的周期(以毫秒计)来调用函数或计算表达式.方法会不停地调用函 ...
- mybatis在spring(Controller) 中的事务配置问题
这两天一直在折腾一个小工具,非常简单的移动端webapp. 用的是jquery mobile + ssm. 写的差不多的时候,想到解决事务问题,本来以为非常简单,只要在配置文件中加上相应的mybati ...
- pyquery:轻松、灵活的处理html
介绍 pyquery是一个专门用来解析html的库,从名字很容易想到jQuery,没错,这完全是仿照jQuery的语法实现的.如果用过jQuery,那么pyquery也很容易上手 初始化html py ...
- 08 自学Aruba之限制应用流量
点击返回:自学Aruba之路点击返回:自学Aruba集锦 08 自学Aruba之限制应用流量 限制带宽请查阅:点击 下文描述的步骤,主要是针对某一个SSID所用用户在使用某一个应用的时候设置共享带宽. ...