题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=2819

  首先根据SG定理,可得若每堆石子数量的异或值为0,则后手必胜,反之先手必胜。于是我们就需要维护一个支持树上单点修改,树链查询异或值的数据结构。

  首先我们可以用树链剖分解决。然而……蒟蒻我比较懒(既懒得写也懒得调),所以我们可以采取一种被用烂了的黑科技:dfs序。

  首先我们会发现,我们可以把查询一条链拆成查询两个端点到根的链的异或值,以及lca的权值。这样一个点的权值修改,查询时只对他的子树有贡献。所以我们可以求出树的dfs序,然后把单点修改转为区间修改,把树链查询转化为单点查询。

  然后为了代码方便,我们可以差分,把区间l~r修改转为修改l、r+1,查询单点k转化为查询1~k的异或值,就能用树状数组维护了。

  代码:

#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define ull unsigned long long
#define max(a,b) (a>b?a:b)
#define min(a,b) (a<b?a:b)
#define lowbit(x) (x& -x)
#define mod 1000000007
#define inf 0x3f3f3f3f
#define eps 1e-18
#define maxn 500010
inline ll read()
{
ll tmp=; char c=getchar(),f=;
for(;c<''||''<c;c=getchar())if(c=='-')f=-;
for(;''<=c&&c<='';c=getchar())tmp=(tmp<<)+(tmp<<)+c-'';
return tmp*f;
}
struct edge{
int to,nxt;
}e[*maxn];
int fir[maxn],pos[maxn],l[maxn],r[maxn],val[maxn],vis[maxn],dep[maxn];
int fa[maxn][];
int bit[maxn];
int n,q,tot=,cnt=;
char op[];
void add(int x,int y){e[tot].to=y; e[tot].nxt=fir[x]; fir[x]=tot++;}
void dfs(int now)
{
vis[now]=; l[now]=pos[now]=++cnt;
for(int i=fir[now];~i;i=e[i].nxt)
if(!vis[e[i].to]){
fa[e[i].to][]=now; dep[e[i].to]=dep[now]+; dfs(e[i].to);
}
r[now]=cnt;
}
inline int getlca(int x,int y)
{
if(dep[x]<dep[y]){int tmp=x; x=y; y=tmp;}
int k=int(log(n)/log());
for(int i=k;i>=;i--)
if(dep[x]-(<<i)>=dep[y])x=fa[x][i];
if(x==y)return x;
for(int i=k;i>=;i--)
if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
return fa[x][];
}
void change(int x,int k){if(x>n)return; for(;x<=n;x+=lowbit(x))bit[x]^=k;}
int getxor(int x){int ans=; for(;x;x-=lowbit(x))ans^=bit[x]; return ans;}
int main()
{
memset(fir,,sizeof(fir));
int i,j;
n=read();
for(i=;i<=n;i++)val[i]=read();
for(i=;i<n;i++){
int x=read(),y=read(); add(x,y); add(y,x);
}
vis[]=; fa[][]=; dep[]=; dfs();
for(j=;<<j<=n;j++)
for(i=;i<=n;i++)
if(fa[i][j-])fa[i][j]=fa[fa[i][j-]][j-];
q=read();
for(i=;i<=n;i++)change(l[i],val[i]),change(r[i]+,val[i]);
for(i=;i<=q;i++){
scanf("%s",op);
if(op[]=='Q'){
int u=read(),v=read();
int tmp=getxor(pos[u])^getxor(pos[v])^val[getlca(u,v)];
if(tmp)printf("Yes\n"); else printf("No\n");
}
else{
int u=read(),k=read();
change(l[u],k^val[u]); change(r[u]+,k^val[u]); val[u]=k;
}
}
}

bzoj2819

  虽然我用的是普通dfs,但是好像bzoj的栈空间挺大的,并不会爆。(不过还是哪天改个人工栈吧)

【bzoj2819】Nim(dfs序+树状数组/线段树)的更多相关文章

  1. 洛谷P2414 阿狸的打字机 [NOI2011] AC自动机+树状数组/线段树

    正解:AC自动机+树状数组/线段树 解题报告: 传送门! 这道题,首先想到暴力思路还是不难的,首先看到y有那么多个,菜鸡如我还不怎么会可持久化之类的,那就直接排个序什么的然后按顺序做就好,这样听说有7 ...

  2. 树状数组 && 线段树应用 -- 求逆序数

    参考:算法学习(二)——树状数组求逆序数 .线段树或树状数组求逆序数(附例题) 应用树状数组 || 线段树求逆序数是一种很巧妙的技巧,这个技巧的关键在于如何把原来单纯的求区间和操作转换为 求小于等于a ...

  3. hdu1394(枚举/树状数组/线段树单点更新&区间求和)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意:给出一个循环数组,求其逆序对最少为多少: 思路:对于逆序对: 交换两个相邻数,逆序数 +1 ...

  4. hdu 1166:敌兵布阵(树状数组 / 线段树,入门练习题)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  5. hdu 5147 Sequence II【树状数组/线段树】

    Sequence IITime Limit: 5000/2500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem ...

  6. POJ3321[苹果树] 树状数组/线段树 + dfs序

    Apple Tree Time Limit: 2000MS   Memory Limit: 65536K Total Submissions:39452   Accepted: 11694 Descr ...

  7. 【poj2182】【poj2828】树状数组/线段树经典模型:逆序查找-空位插入法

    poj2182题意:有一个1~n的排列,现在给定每个人前面有多少个人的编号比他大,求这个排列是什么.n<=8000 poj2182题解: 逆序做,可以确定二分最后一个是什么,然后删除这个数.树状 ...

  8. HDU 5293 Train chain Problem - 树链剖分(树状数组) + 线段树+ 树型dp

    传送门 题目大意: 一颗n个点的树,给出m条链,第i条链的权值是\(w_i\),可以选择若干条不相交的链,求最大权值和. 题目分析: 树型dp: dp[u][0]表示不经过u节点,其子树的最优值,dp ...

  9. [CSP-S模拟测试]:影魔(树状数组+线段树合并)

    题目背景 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...

随机推荐

  1. 山石防火墙debug

    debug dp basic debug dp snoop debup dp drop debug dp filter src-ip ? show logging debug

  2. 《从零开始学Swift》学习笔记(Day 42)——构造函数调用规则

    原创文章,欢迎转载.转载请注明:关东升的博客 在构造函数中可以使用构造函数代理帮助完成部分构造工作.类构造函数代理分为横向代理和向上代理,横向代理只能在发生在同一类内部,这种构造函数称为便利构造函数. ...

  3. 安装mysql报错—解决方法:error while loading shared libraries: libssl.so.6

    for 32bit ln -sf /usr/lib/libssl.so.10 /usr/lib/libssl.so.6ln -sf /usr/lib/libcrypto.so.10 /usr/lib/ ...

  4. 关于自我总结的html5新特性

    最近本包子制订了一个学校计划,第一步就是了解并总结一下html5现在所含有的新特性,好吧,这只是一个了解,- -! 自己总结了一个word文档,里面很多东西自己都还没实际用过,下一步,本包子要写pc端 ...

  5. Introduction to Mathematical Thinking - Week 2

    基本数学概念 real number(实数):是有理数和无理数的总称 有理数:可以表达为两个整数比的数(a/b, b!=0) 无理数是指除有理数以外的实数 imply -- 推导出 不需要 A 能推导 ...

  6. if you have content fetched asynchronously on pages where SEO is important, SSR might be necessary

    if you have content fetched asynchronously on pages where SEO is important, SSR might be necessary

  7. E QUERY [main] SyntaxError: identifier starts immediately after numeric literal mongodb mapReduce 异常分析 集合命名规范

    异常信息 repl_test:PRIMARY> db.0917order_totals_b.find()2018-09-28T15:13:03.992+0800 E QUERY [main] S ...

  8. django实现密码加密的注册(数据对象插入)

    在 django实现密码非加密的注册(数据对象插入)的基础上,我们对视图和注册页面进行了简单修改 视图 from django.shortcuts import render,redirect,ren ...

  9. where VS having

    where 和 having 的区别:        WHERE 子句不能包含聚集函数: 因为试图用聚集函数判断那些行输入给聚集运算是没有意义的.相反,HAVING 子句总是包含聚集函数    hav ...

  10. 【Nginx】HTTP请求的11个处理阶段

    Nginx将一个HTTP请求分成多个阶段.以模块为单位进行处理.这样做的优点是使处理过程更加灵活.减少耦合度.HTTP框架将处理分成了11个阶段,各个阶段能够包括随意多个HTTP模块并以流水线的方式处 ...