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

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

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

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

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

  代码:

  1. #include<cstdio>
  2. #include<cmath>
  3. #include<cstdlib>
  4. #include<cstring>
  5. #include<ctime>
  6. #include<algorithm>
  7. #include<queue>
  8. #include<vector>
  9. #include<map>
  10. #define ll long long
  11. #define ull unsigned long long
  12. #define max(a,b) (a>b?a:b)
  13. #define min(a,b) (a<b?a:b)
  14. #define lowbit(x) (x& -x)
  15. #define mod 1000000007
  16. #define inf 0x3f3f3f3f
  17. #define eps 1e-18
  18. #define maxn 500010
  19. inline ll read()
  20. {
  21. ll tmp=; char c=getchar(),f=;
  22. for(;c<''||''<c;c=getchar())if(c=='-')f=-;
  23. for(;''<=c&&c<='';c=getchar())tmp=(tmp<<)+(tmp<<)+c-'';
  24. return tmp*f;
  25. }
  26. struct edge{
  27. int to,nxt;
  28. }e[*maxn];
  29. int fir[maxn],pos[maxn],l[maxn],r[maxn],val[maxn],vis[maxn],dep[maxn];
  30. int fa[maxn][];
  31. int bit[maxn];
  32. int n,q,tot=,cnt=;
  33. char op[];
  34. void add(int x,int y){e[tot].to=y; e[tot].nxt=fir[x]; fir[x]=tot++;}
  35. void dfs(int now)
  36. {
  37. vis[now]=; l[now]=pos[now]=++cnt;
  38. for(int i=fir[now];~i;i=e[i].nxt)
  39. if(!vis[e[i].to]){
  40. fa[e[i].to][]=now; dep[e[i].to]=dep[now]+; dfs(e[i].to);
  41. }
  42. r[now]=cnt;
  43. }
  44. inline int getlca(int x,int y)
  45. {
  46. if(dep[x]<dep[y]){int tmp=x; x=y; y=tmp;}
  47. int k=int(log(n)/log());
  48. for(int i=k;i>=;i--)
  49. if(dep[x]-(<<i)>=dep[y])x=fa[x][i];
  50. if(x==y)return x;
  51. for(int i=k;i>=;i--)
  52. if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
  53. return fa[x][];
  54. }
  55. void change(int x,int k){if(x>n)return; for(;x<=n;x+=lowbit(x))bit[x]^=k;}
  56. int getxor(int x){int ans=; for(;x;x-=lowbit(x))ans^=bit[x]; return ans;}
  57. int main()
  58. {
  59. memset(fir,,sizeof(fir));
  60. int i,j;
  61. n=read();
  62. for(i=;i<=n;i++)val[i]=read();
  63. for(i=;i<n;i++){
  64. int x=read(),y=read(); add(x,y); add(y,x);
  65. }
  66. vis[]=; fa[][]=; dep[]=; dfs();
  67. for(j=;<<j<=n;j++)
  68. for(i=;i<=n;i++)
  69. if(fa[i][j-])fa[i][j]=fa[fa[i][j-]][j-];
  70. q=read();
  71. for(i=;i<=n;i++)change(l[i],val[i]),change(r[i]+,val[i]);
  72. for(i=;i<=q;i++){
  73. scanf("%s",op);
  74. if(op[]=='Q'){
  75. int u=read(),v=read();
  76. int tmp=getxor(pos[u])^getxor(pos[v])^val[getlca(u,v)];
  77. if(tmp)printf("Yes\n"); else printf("No\n");
  78. }
  79. else{
  80. int u=read(),k=read();
  81. change(l[u],k^val[u]); change(r[u]+,k^val[u]); val[u]=k;
  82. }
  83. }
  84. }

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. 误: Apache shutdown unexpectedly解决办法

    from:http://www.wopus.org/wordpress-basic/getting-started/2536.htmlXAMPP错  2015年10月20日15:58:19 新手上路发 ...

  2. PowerDesigner之设置(1)

    这里用到的数据库为SQL2000. PowerDesigner 16. 原始格式: (个人认为的缺点) 创建表前先将原来的表删除(创建表逻辑,假如存在则drop.假如原来有数据,用drop就有问题.新 ...

  3. Farm Tour(最小费用最大流模板)

    Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18150   Accepted: 7023 Descri ...

  4. JSON工具类库: alibaba/fastjson 使用记录

    JSON工具类库: alibaba/fastjson 使用记录 一.了解JSON JSON标准规范中文文档: http://www.json.org/json-zh.html 最佳实践:http:// ...

  5. sqlserver 脚本和批处理指令小结

    一.脚本基础     1.USE语句          设置当前数据库.     2.声明变量          语法:DECLARE @变量名 变量类型          在声明变量后,给变量赋值之 ...

  6. java读取本地文件

    File file = new File("F:/hejing/InstrumentJsonData.txt");        StringBuilder localStrBul ...

  7. Tomcat 配置连接池

    1. Tomcat 配置 JNDI 资源 JNDI(Java Naming and Directory Interface), Java 命名和目录接口; JNDI 作用: 在服务器上配置资源, 然后 ...

  8. django注册在使用hashlib对密码加密时报Unicode-objects must be encoded before hashing

    在使用sh1等hashlib方法进行加密时报:Unicode-objects must be encoded before hashing 解决办法:对要加密的字符串指定编码格式 解决之前: s1=s ...

  9. 通过Python操作hbase api

    # coding=utf-8 # Author: ruin """ discrible: """ from thrift.transport ...

  10. virt-viewer的简单使用

    virt-viewer 简介:  virt-viewer是一个用于显示虚拟机的图形控制台的最小工具. 控制台使用VNC或SPICE访问协议. 可以基于其名称,ID或UUID来引用guest虚拟机.如果 ...