UOJ#266. 【清华集训2016】Alice和Bob又在玩游戏 博弈,DSU on Tree,Trie
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ266.html
题解
首先我们可以直接暴力 $O(n^2)$ 用 sg 函数来算答案。
对于一个树就是枚举一下从根出发到哪一个节点为止的路径被删掉了,剩下所有的子树的sg值xor起来,对于每一个路径后的答案取一个 mex 。
我们考虑快速的做这个过程。
直接写个 Trie 再 DSU on tree 就好了,只要支持查询 mex 和整棵 trie 对某一个值 xor 这两种操作就好了。
时间复杂度 $O(n\log ^2n)$ 。
P.S. 可以用线段树合并优化复杂度。
代码
#pragma GCC optimize("Ofast","inline")
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
#define For(i,a,b) for (int i=a;i<=b;i++)
#define Fod(i,b,a) for (int i=b;i>=a;i--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define _SEED_ ('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')
#define outval(x) printf(#x" = %d\n",x)
#define outvec(x) printf("vec "#x" = ");for (auto _v : x)printf("%d ",_v);puts("")
#define outtag(x) puts("----------"#x"----------")
#define outarr(a,L,R) printf(#a"[%d...%d] = ",L,R);\
For(_v2,L,R)printf("%d ",a[_v2]);puts("");
using namespace std;
typedef long long LL;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=100005;
namespace Trie{
const int S=N*20*20;
int son[S][2],size[S],c=0;
#define ls son[x][0]
#define rs son[x][1]
void Init(){
while (c)
clr(son[c]),size[c]=0,c--;
}
void Ins(int &x,int d,int v,int tag){
if (!x)
x=++c,size[x]=1;
if (d<0)
return;
Ins(son[x][(v^tag)>>d&1],d-1,v,tag);
size[x]=size[ls]+size[rs];
}
void Get(int x,int d,int v,int tag,vector <int> &vec){
if (!x)
return;
if (d<0)
return vec.pb(v);
Get(son[x][tag>>d&1],d-1,v,tag,vec);
Get(son[x][~tag>>d&1],d-1,v|(1<<d),tag,vec);
}
int Ask(int x,int d,int v,int tag){
if (d<0)
return v;
if (size[son[x][tag>>d&1]]<(1<<d))
return Ask(son[x][tag>>d&1],d-1,v,tag);
else
return Ask(son[x][~tag>>d&1],d-1,v|(1<<d),tag);
}
#undef ls
#undef rs
}
int n,m;
vector <int> e[N];
struct trie{
int rt,tag;
}t[N];
int cnt;
int size[N],son[N],sg[N],id[N];
void dfs(int x,int pre){
size[x]=1,son[x]=0;
for (auto y : e[x])
if (y!=pre){
dfs(y,x);
size[x]+=size[y];
if (!son[x]||size[son[x]]<size[y])
son[x]=y;
}
}
vector <int> gid;
void dfs2(int x,int pre){
sg[x]=0;
int s=0;
for (auto y : e[x])
if (y!=pre){
dfs2(y,x);
s^=sg[y];
}
if (!son[x])
id[x]=++cnt,t[cnt].rt=t[cnt].tag=0;
else
t[id[x]=id[son[x]]].tag^=s^sg[son[x]];
trie &now=t[id[x]];
Trie::Ins(now.rt,17,s,now.tag);
for (auto y : e[x])
if (y!=pre&&y!=son[x]){
gid.clear();
Trie::Get(t[id[y]].rt,17,0,t[id[y]].tag,gid);
for (auto v : gid)
Trie::Ins(now.rt,17,v^(s^sg[y]),now.tag);
}
sg[x]=Trie::Ask(now.rt,17,0,now.tag);
}
void Main(){
n=read(),m=read();
For(i,0,n)
e[i].clear(),size[i]=0;
For(i,1,m){
int x=read(),y=read();
e[x].pb(y),e[y].pb(x);
}
cnt=0;
int ans=0;
Trie::Init();
For(i,1,n)
if (!size[i]){
dfs(i,0);
dfs2(i,0);
ans^=sg[i];
}
puts(ans?"Alice":"Bob");
}
int main(){
int T=read();
while (T--)
Main();
return 0;
}
UOJ#266. 【清华集训2016】Alice和Bob又在玩游戏 博弈,DSU on Tree,Trie的更多相关文章
- 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\)即可.注意计算后继的时候可以直接从父亲转移过来,没必 ...
- [UOJ#274][清华集训2016]温暖会指引我们前行
[UOJ#274][清华集训2016]温暖会指引我们前行 试题描述 寒冬又一次肆虐了北国大地 无情的北风穿透了人们御寒的衣物 可怜虫们在冬夜中发出无助的哀嚎 “冻死宝宝了!” 这时 远处的天边出现了一 ...
- [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又在玩游戏(博弈论)
传送门 完了我连sg函数是个啥都快忘了 设\(sg[u]\)为以\(u\)为根节点的子树的\(sg\)函数值,\(rem[u]\)表示\(u\)到根节点的路径删掉之后剩下的游戏的异或值 根节点\(u\ ...
- UOJ 266 - 【清华集训2016】Alice和Bob又在玩游戏(SG 定理+01-trie)
题面传送门 神仙题. 首先注意到此题的游戏是一个 ICG,故考虑使用 SG 定理解决这个题,显然我们只需对每个连通块计算一遍其 SG 值异或起来检验是否非零即可.注意到我们每删除一个点到根节点的路径后 ...
- 【清华集训2016】Alice和Bob又在玩游戏
不难的题目.因为SG性质,所以只需要对一棵树求出. 然后如果发现从上往下DP不太行,所以从下往上DP. 考虑一个点对子树的合并,考虑下一个删的点在哪一个子树,那么剩下的状态实际上就是把一个子树所有能达 ...
随机推荐
- 原生js实现平滑滚动
在以前的项目中有用到,在此整理一下: html部分 <span id="gotop">回到顶部</span> JS部分 // 使用requestAnimat ...
- SaltStack配置管理和YAML
配置管理和YAML 配置管理 所谓的配置管理,也称为状态管理,就是可以通过编写文件,文件的内容为安装什么功能.开启什么服务,执行什么任务等信息,然后通过salt的配置管理,指定minion来执行这些操 ...
- 阿里云Redis开发规范
转自: https://yq.aliyun.com/articles/531067 摘要: 本文介绍了在使用阿里云Redis的开发规范,从键值设计.命令使用.客户端使用.相关工具等方面进行说明,通过本 ...
- 把xml数据直接插入到sqlserver数据库
存储过程: ALTER proc [ali].[ins_冻结金额表] @xmldoc varchar(max), ) as declare @idoc int exec sp_xml_prepared ...
- python8--文件操作 with。。。open语法
复习 一.类型转换 1.数字类型:int() | bool() | float() 2.str与int:int('10') | int('-10') | int('0') | float('-. ...
- js重点--匿名函数
推荐博客:https://www.cnblogs.com/pssp/p/5216668.html 函数是必须要有函数名的,不然没有办法找到它,使用它. 如果没有名字必须要有一个依附体,如:将这个匿名函 ...
- npm_config_
npm script时会带一些参数变量,例如: "test": "node scripts/tools/test.js --name=test111" 平常我们 ...
- Guest Editors’ Introduction: Special Issue on Advances in Management of Softwarized Networks
文章名称:Guest Editors’ Introduction:Special Issue on Advances in Management of Softwarized Networks 发表时 ...
- [Reinforcement Learning] Model-Free Control
上篇总结了 Model-Free Predict 问题及方法,本文内容介绍 Model-Free Control 方法,即 "Optimise the value function of a ...
- Livereload or meta
静态页面布局的过程中,如果可以一边写一边看见结果,那肯定是很方便的,在最开始使用的DW中实现了这一目标,但并不是浏览器环境下.之后使用gulp中的livereload后配合chrome插件livere ...