原文链接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的更多相关文章

  1. uoj266[清华集训2016]Alice和Bob又在玩游戏(SG函数)

    uoj266[清华集训2016]Alice和Bob又在玩游戏(SG函数) uoj 题解时间 考虑如何求出每棵树(子树)的 $ SG $ . 众所周知一个状态的 $ SG $ 是其后继的 $ mex $ ...

  2. UOJ #266 【清华集训2016】 Alice和Bob又在玩游戏

    题目链接:Alice和Bob又在玩游戏 这道题就是一个很显然的公平游戏. 首先\(O(n^2)\)的算法非常好写.暴力枚举每个后继计算\(mex\)即可.注意计算后继的时候可以直接从父亲转移过来,没必 ...

  3. [UOJ#274][清华集训2016]温暖会指引我们前行

    [UOJ#274][清华集训2016]温暖会指引我们前行 试题描述 寒冬又一次肆虐了北国大地 无情的北风穿透了人们御寒的衣物 可怜虫们在冬夜中发出无助的哀嚎 “冻死宝宝了!” 这时 远处的天边出现了一 ...

  4. [UOJ266]Alice和Bob又在玩游戏

    [UOJ266]Alice和Bob又在玩游戏 Tags:题解 作业部落 评论地址 TAG:博弈 题意 不同于树的删边游戏,删掉一个点删去的是到根的路径 题解 这题只和计算\(SG\)有关,博弈的有关内 ...

  5. [BZOJ4730][清华集训2016][UOJ266] Alice和Bob又在玩游戏

    题意:俩智障又在玩游戏.规则如下: 给定n个点,m条无向边(m<=n-1),保证无环,对于每一个联通块,编号最小的为它们的根(也就是形成了一片这样的森林),每次可以选择一个点,将其本身与其祖先全 ...

  6. bzoj4730: Alice和Bob又在玩游戏

    Description Alice和Bob在玩游戏.有n个节点,m条边(0<=m<=n-1),构成若干棵有根树,每棵树的根节点是该连通块内编号最 小的点.Alice和Bob轮流操作,每回合 ...

  7. uoj#266. 【清华集训2016】Alice和Bob又在玩游戏(博弈论)

    传送门 完了我连sg函数是个啥都快忘了 设\(sg[u]\)为以\(u\)为根节点的子树的\(sg\)函数值,\(rem[u]\)表示\(u\)到根节点的路径删掉之后剩下的游戏的异或值 根节点\(u\ ...

  8. UOJ 266 - 【清华集训2016】Alice和Bob又在玩游戏(SG 定理+01-trie)

    题面传送门 神仙题. 首先注意到此题的游戏是一个 ICG,故考虑使用 SG 定理解决这个题,显然我们只需对每个连通块计算一遍其 SG 值异或起来检验是否非零即可.注意到我们每删除一个点到根节点的路径后 ...

  9. 【清华集训2016】Alice和Bob又在玩游戏

    不难的题目.因为SG性质,所以只需要对一棵树求出. 然后如果发现从上往下DP不太行,所以从下往上DP. 考虑一个点对子树的合并,考虑下一个删的点在哪一个子树,那么剩下的状态实际上就是把一个子树所有能达 ...

随机推荐

  1. C# Linq to Entity 多条件 OR查询

    技术背景:框架MVC,linq to Entity 需要一定的lambda书写能力 问题:在简单的orm中完成一些简单的增删查改是通过where insert delete update 完成的,但是 ...

  2. 2017-12-20python全栈9期第五天第二节之可变 数据类型和不可变数据类型

  3. 04--STL序列容器(Stack和Queue)

    总括: stack和queue不支持迭代 一:栈Stack (一)栈的简介 stack是堆栈容器,是一种“先进后出”的容器. stack是简单地装饰deque容器而成为另外的一种容器. (二)栈的默认 ...

  4. npm install 时出现的 EACCES: permission denied 错误的可能有效的解决方案

    最近我开始接触手机 app 的编写,公司用到了 Nativescript.当我下载了公司的项目后,在配置时出现了不少的问题,其中出现概率最高的就是 EACCES: permission denied ...

  5. H5_0002:微信分享设置

    1,非公众号的链接,设置分享的预览图片. 先打开页面,在收藏页面,最后在收藏界面长按 “转发” ,即可在链接上出现预览图片.

  6. [Android] Android 手机下 仿 今日头条 新闻客户端

    利用一个月的时间,自学了 Android 开发 ,为了检验学习成果,特意 开发了这个  仿 今日头条 新闻客户端 AppNews 包括图文新闻+视频新闻+图片新闻 预览演示如下: 功能说明: 1)底部 ...

  7. 利用JS写一个计算平方的网页

    <!-- 计算一个数的平方并显示出来 --> <!DOCTYPE html> <html> <head> <meta charset=" ...

  8. WebGL&Three.js工作原理

    一.我们讲什么? 我们讲两个东西:1.WebGL背后的工作原理是什么?2.以Three.js为例,讲述框架在背后扮演什么样的角色? 二.我们为什么要了解原理? 我们假定你对WebGL已经有一定了解,或 ...

  9. python3 练手实例7 斐波那契数列

    '''a,b=0,1 x=int(input('请指定需要多少项:')) while x>0: print(b) a,b=b,a+b x-=1''' #递归 def fibo(n): if n& ...

  10. 原生JS实现简易评论更新功能

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...