著名游戏设计师vfleaking,最近迷上了Nim。普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取。谁不能取谁输。这个游戏是有必胜策略的。于是vfleaking决定写一个玩Nim游戏的平台来坑玩家。
为了设计漂亮一点的初始局面,vfleaking用以下方式来找灵感:拿出很多石子,把它们聚成一堆一堆的,对每一堆编号1,2,3,4,...n,在堆与堆间连边,没有自环与重边,从任意堆到任意堆都只有唯一一条路径可到达。然后他不停地进行如下操作:

1.随机选两个堆v,u,询问若在v到u间的路径上的石子堆中玩Nim游戏,是否有必胜策略,如果有,vfleaking将会考虑将这些石子堆作为初始局面之一,用来坑玩家。
2.把堆v中的石子数变为k。

由于vfleaking太懒了,他懒得自己动手了。请写个程序帮帮他吧。

题意:给定一棵树,每个节点上有个数值,现在Q个操作:

一种操作是给定u,v,然后需要回答u到v的最短路径上的这些数的Nim博弈结果。

一种操作是给定x,val,然后需要把x节点上的数值改为val。

思路:1,树剖,就不多说了。

2,dfs序可以得到u到根root的节点信息,所以sum(u,v)=sum(u,LCA)^sum(v,son[LCA])=sum(1,u)^sum(1,fa[v])。

具体的得到根到节点信息,可以参考这道题:https://blog.csdn.net/clove_unique/article/details/70213935

虽然第二种简单很多,这里树剖练习,先不管它:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=;
int a[maxn],sum[maxn<<],top[maxn],sz[maxn],son[maxn];
int Laxt[maxn],Next[maxn<<],To[maxn<<],cnt,N,Q;
int fa[maxn],dep[maxn],times,tid[maxn],Rank[maxn];
void add(int u,int v)
{
Next[++cnt]=Laxt[u];
Laxt[u]=cnt;
To[cnt]=v;
}
void dfs1(int u,int pre)
{
sz[u]=; fa[u]=pre; dep[u]=dep[pre]+;
for(int i=Laxt[u];i;i=Next[i]){
int v=To[i];
if(v==pre) continue;
dfs1(v,u);
sz[u]+=sz[v];
if(sz[v]>sz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int Top)
{
tid[u]=++times; Rank[times]=u; top[u]=Top;
if(son[u]) dfs2(son[u],Top);
for(int i=Laxt[u];i;i=Next[i]){
int v=To[i];
if(v==fa[u]||v==son[u]) continue;
dfs2(v,v);
}
}
void update(int Now)
{
sum[Now]=sum[Now<<]^sum[Now<<|];
}
void build(int Now,int L,int R)
{
if(L==R){
sum[Now]=a[Rank[L]];
return ;
}
int Mid=(L+R)>>;
build(Now<<,L,Mid);
build(Now<<|,Mid+,R);
update(Now);
}
int getsum(int Now,int L,int R,int l,int r)
{
if(l<=L&&r>=R) return sum[Now];
int Mid=(L+R)>>,res=;
if(l<=Mid) res^=getsum(Now<<,L,Mid,l,r);
if(r>Mid) res^=getsum(Now<<|,Mid+,R,l,r);
return res;
}
int query(int u,int v)
{
int res=;
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]]) swap(u,v);
res^=getsum(,,N,tid[top[u]],tid[u]);
u=fa[top[u]];
}
if(dep[u]>dep[v]) swap(u,v);
res^=getsum(,,N,tid[u],tid[v]);
return res;
}
void change(int Now,int L,int R,int pos,int val)
{
if(L==R){
sum[Now]=val; return ;
}
int Mid=(L+R)>>;
if(pos<=Mid) change(Now<<,L,Mid,pos,val);
else change(Now<<|,Mid+,R,pos,val);
update(Now);
}
int main()
{
int u,v,i; char opt[];
scanf("%d",&N);
for(i=;i<=N;i++) scanf("%d",&a[i]);
for(i=;i<N;i++){
scanf("%d%d",&u,&v);
add(u,v); add(v,u);
}
dfs1(,); dfs2(,); build(,,N);
scanf("%d",&Q);
while(Q--){
scanf("%s%d%d",opt,&u,&v);
if(opt[]=='Q'){
if(query(u,v)) printf("Yes\n");
else puts("No");
}
else change(,,N,tid[u],v);
}
return ;
}

BZOJ:2819 NIM(树链剖分||DFS序 &&NIM博弈)的更多相关文章

  1. BZOJ 3083: 遥远的国度(树链剖分+DFS序)

    可以很显而易见的看出,修改就是树链剖分,而询问就是在dfs出的线段树里查询最小值,但由于这道题会修改根节点,所以在查询的时候需判断x是否为root的祖先,如果不是就直接做,是的话应该查询从1-st[y ...

  2. BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA]

    3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 1280 MBSubmit: 3127  Solved: 795[Submit][Status][Discu ...

  3. [BZOJ - 2819] Nim 【树链剖分 / DFS序】

    题目链接: BZOJ - 2819 题目分析 我们知道,单纯的 Nim 的必胜状态是,各堆石子的数量异或和不为 0 .那么这道题其实就是要求求出树上的两点之间的路径的异或和.要求支持单点修改. 方法一 ...

  4. 树链剖分&dfs序

    树上问题 很多处理区间的问题(像是RMQ,区间修改).可以用线段树,树状数组,ST表这些数据结构来维护.但是如果将这些问题挪到了树上,就不能直接用这些数据结构来处理了.这时就用到了dfs序和树链剖分. ...

  5. BZOJ_4034 [HAOI2015]树上操作 【树链剖分dfs序+线段树】

    一 题目 [HAOI2015]树上操作 二 分析 树链剖分的题,这里主要用到了$dfs$序,这题比较简单的就是不用求$lca$. 1.和树链剖分一样,先用邻接链表建双向图. 2.跑两遍$dfs$,其实 ...

  6. 树链剖分||dfs序 各种题

    1.[bzoj4034][HAOI2015]T2 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把 ...

  7. BZOJ 4196: [Noi2015]软件包管理器 [树链剖分 DFS序]

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1352  Solved: 780[Submit][Stat ...

  8. BZOJ 2286 树链剖分+DFS序+虚树+树形DP

    第一次学习虚树,就是把无关的点去掉.S里维护一条链即可. #include <iostream> #include <cstring> #include <cstdio& ...

  9. BZOJ - 4196 软件包管理器 (树链剖分+dfs序+线段树)

    题目链接 设白色结点为未安装的软件,黑色结点为已安装的软件,则: 安装软件i:输出结点i到根的路径上的白色结点的数量,并把结点i到根的路径染成黑色.复杂度$O(nlog^2n)$ 卸载软件i:输出结点 ...

随机推荐

  1. hls简述(HTTP live Streaming)

    hls官方地址:https://developer.apple.com/streaming/ IDR: Instantaneous Decoding Refresh (IDR) start code ...

  2. 【ITOO 3】.NET 动态建库建表:实用EF框架提供的codeFirst实现动态建库

    导读:在上篇博客中,介绍了使用SQL字符拼接的方式,实现动态建库建表的方法.这样做虽然也能够实现效果,但是,太麻烦,而且,如果改动表结构,字段的话,会对代码修改很多.但是EF给我们提供了一种代码先行的 ...

  3. Codeforces Round #269 (Div. 2)-D. MUH and Cube Walls,KMP裸模板拿走!

    D. MUH and Cube Walls 说实话,这题看懂题意后秒出思路,和顺波说了一下是KMP,后来过了一会确定了思路他开始写我中途接了个电话,回来kaungbin模板一板子上去直接A了. 题意: ...

  4. NYOJ-673悟空的难题~~水题~~

    悟空的难题 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 自从悟空当上了齐天大圣,花果山上的猴子猴孙们便也可以尝到天上的各种仙果神酒,所以猴子猴孙们的体质也得到了很好的 ...

  5. HDU1021-Fibonacci Again,,找规律就好了~~~

    Fibonacci Again Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  6. 日志不得应用情况切换强制standby改变状态为primary

    日志不得应用情况切换备库为主库 备库运行如下: alter database recover managed standby database disconnect from session; alt ...

  7. HDU 1078 dfs+dp

    题目大意: 在n*n的矩阵中,每个格子放置了一定数量的食物,一只老鼠每次水平或竖直最多移动k格,每次到的位置食物都要比前一次多,问最后一共能得到多少食物 这道题利用记忆化搜索做,利用nowstate不 ...

  8. bzoj 3207 花神的嘲讽计划Ⅰ 主席树+hash

    花神的嘲讽计划Ⅰ Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 3112  Solved: 1086[Submit][Status][Discuss] ...

  9. 【NOIP模拟&POJ2152】灰色的果实(树形DP)

    题意: Nebula 历 2014 年 12 月 17 日,欢迎来到异世界. 面对截然不同的新世界,你决定采取最普通但最为有效的方式来探索,那便 是徒步.准备好营地的一切,你开始了探索的旅程. 步行大 ...

  10. POJ3150:Cellular Automaton

    题意看不懂加题目想不通,很菜. n<=500个数围城环,每次操作对每个数Ai把与i在环上相距不超过d<n/2(包括Ai)的数加起来取模m<=1e6,求K<=1e7次操作后的环. ...