【题目大意】

普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取。谁不能取谁输。这个游戏是有必胜策略的。现在对每一堆编号1,2,3,4,...n,在堆与堆间连边,没有自环与重边,从任意堆到任意堆都只有唯一一条路径可到达。然后他不停地进行如下操作:
1.随机选两个堆v,u,询问若在v到u间的路径上的石子堆中玩Nim游戏,是否有必胜策略,如果有,vfleaking将会考虑将这些石子堆作为初始局面之一,用来坑玩家。
2.把堆v中的石子数变为k。

【思路】

对于普通的Nim游戏,如果所有石子数量异或和为1,则必胜,否则不能。

现在这些堆组成了一棵树,我们用query(x)表示从x到根节点的异或值,显然u到v的路径上的异或和胃query(u) xor query(v) xor (num[lca(u,v)])(因为它们的最近公共祖先被重复异或了两次,抵消掉了,所以又要异或回来。)

第一种做法就是用数量剖分,映射到线段树上去解决。

由于每个u的值改变,它仅仅会影响到它及它子树的query值,而且一个节点及其子树的dfs序是连续的,可以用树状数组来维护一下。

关于利用dfs序相同性质的一道题目,和AC自动机结合更困难些→

树状数组维护xor和维护和一个道理,相当于一个区间修改点查询的树状数组。注意一下修改操作的方法:delta=num[u]^v,这样异或的时候原来的num[u]就抵消了,留下了v。这比较简单,但是不要忘记了修改后要num[u]→v。

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=+;
const int DEG=;
vector<int> E[MAXN];
int start[MAXN],end[MAXN];
int n,num[MAXN],e[MAXN];
int anc[MAXN][DEG],dep[MAXN];
int cnt=; void addedge(int u,int v)
{
E[u].push_back(v);
E[v].push_back(u);
} /*树状数组区间修改点查询部分*/
int lowbit(int x)
{
return (x&(-x));
} void modify(int x,int y,int delta)
{
if (x<y) swap(x,y);
x++;
while (x<MAXN) e[x]^=delta,x+=lowbit(x);
while (y<MAXN) e[y]^=delta,y+=lowbit(y);
} int query(int x)
{
int ret=;
while(x) ret^=e[x],x-=lowbit(x);
return ret;
} /*dfs序部分及lca的初始化*/
void dfs(int u,int fa,int d)
{
dep[u]=d;
anc[u][]=fa;
start[u]=++cnt;
for (int i=;i<E[u].size();i++)
if (E[u][i]!=fa) dfs(E[u][i],u,d+);
end[u]=cnt;
} /*lca部分*/
void getanc()
{
for (int i=;i<DEG;i++)
for (int j=;j<=n;j++)
anc[j][i]=anc[anc[j][i-]][i-];
} int swim(int u,int H)
{
int i=;
while (H)
{
if (H&) u=anc[u][i];
i++;
H>>=;
}
return u;
} int lca(int u,int v)
{
if (dep[u]<dep[v]) swap(u,v);
u=swim(u,dep[u]-dep[v]);
if (u==v) return u;
for (int i=DEG-;i>=;i--)
{
if (anc[u][i]!=anc[v][i])
{
u=anc[u][i];
v=anc[v][i];
}
}
return anc[u][];
} /*main*/
void init()
{
scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%d",&num[i]);
for (int i=;i<n-;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
}
dfs(,,);
getanc();
memset(e,,sizeof(e));
for (int i=;i<=n;i++) modify(start[i],end[i],num[i]);
} void solve()
{
int q;
scanf("%d",&q);
for (int i=;i<q;i++)
{
char c[];int u,v;
scanf("%s%d%d",c,&u,&v);
if (c[]=='Q')
{
int LCA=lca(u,v);
int ans=query(start[u])^query(start[v])^num[LCA];
if (ans) puts("Yes");else puts("No");
}
else
{
modify(start[u],end[u],num[u]^v);
num[u]=v;
}
}
} int main()
{
init();
solve();
return ;
}

【(博弈)dfs序+树状数组】BZOJ2819-Nim的更多相关文章

  1. 【bzoj2819】Nim DFS序+树状数组+倍增LCA

    题目描述 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...

  2. 【BZOJ】2819: Nim(树链剖分 / lca+dfs序+树状数组)

    题目 传送门:QWQ 分析 先敲了个树链剖分,发现无法AC(其实是自己弱,懒得debug.手写栈) 然后去学了学正解 核心挺好理解的,$ query(a) $是$ a $到根的异或和. 答案就是$ l ...

  3. HDU 3887:Counting Offspring(DFS序+树状数组)

    http://acm.hdu.edu.cn/showproblem.php?pid=3887 题意:给出一个有根树,问对于每一个节点它的子树中有多少个节点的值是小于它的. 思路:这题和那道苹果树是一样 ...

  4. HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...

  5. Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组

    C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...

  6. BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )

    一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...

  7. 【bzoj3881】[Coci2015]Divljak AC自动机+树链的并+DFS序+树状数组

    题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...

  8. [BZOJ1103][POI2007]大都市meg dfs序+树状数组

    Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了.不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1..n ...

  9. 2018.10.20 NOIP模拟 巧克力(trie树+dfs序+树状数组)

    传送门 好题啊. 考虑前面的32分,直接维护后缀trietrietrie树就行了. 如果#号不在字符串首? 只需要维护第一个#前面的字符串和最后一个#后面的字符串. 分开用两棵trie树并且维护第一棵 ...

  10. HDU 5293 Annoying problem 树形dp dfs序 树状数组 lca

    Annoying problem 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 Description Coco has a tree, w ...

随机推荐

  1. fundamentals of the jQuery library

    1.why is jquery Only 32kB minified and gzipped. Can also be included as an AMD module Supports CSS3 ...

  2. 【Matlab】绘制饼状统计图

    a=tabulate(b); % b为需要绘制饼图的原始数据列,生成新的一个矩阵a label={'1','2','3'} % 设定饼图每块扇形代表的内容 percent=num2str(a(:,3) ...

  3. python实战===2017年30个惊艳的Python开源项目 (转)

    本文转自:http://www.sohu.com/a/216723120_115128 摘要:本文来自Mybridge,介绍了过去一年里30个惊艳的Python开源项目.点击每一个都可以在GitHub ...

  4. c语言简单实现telnet客户端

    c语言简单实现telnet客户端 http://blog.csdn.net/haiwenchen/article/details/69944118

  5. XMLDocument 方法中实现post发送消息

    XMLDocument 方法中实现post发送消息

  6. C语言面试题总结(一)

    以前的记录都在电子笔记里,倒不如拿出来,有错的地方和大家交流. 1.指针操作: 如下例,设a内存地址为OX00 int a =10; int *p = &a; *a 编译错误 a表示10 *p ...

  7. windows访问linux共享文件夹

    1.windows的网上邻居,是通过smb协议来共享信息的,如果需要给访问linux上的共享目录被windows访问到,需要linux有smb协议 sudo apt-get install samba ...

  8. 【总结】IE和Firefox的Javascript兼容性总结

    长久以来JavaScript兼容性一直是Web开发者的一个主要问题.在正式规范.事实标准以及各种实现之间的存在的差异让许多开发者日夜煎熬.为此,主要从以下几方面差异总结IE和Firefox的Javas ...

  9. iframe弹出框js ie6下存在bug

    ie6的iframe在第一次加载的显示不出来,显示空白,但是很奇怪,刷新就可以正常显示了,一开始以为这只是IE6下iframe加载的bug,但是最后结果发现这是ie6下javascript延迟加载出现 ...

  10. Leetcode 之Binary Tree Postorder Traversal(46)

    采用广度优先遍历,一个变量记录层数,一个变量记录方向. void traverse(TreeNode *root, vector<vector<int>> result, in ...