【bzoj2819】Nim(dfs序+树状数组/线段树)
题目传送门: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序+树状数组/线段树)的更多相关文章
- 洛谷P2414 阿狸的打字机 [NOI2011] AC自动机+树状数组/线段树
正解:AC自动机+树状数组/线段树 解题报告: 传送门! 这道题,首先想到暴力思路还是不难的,首先看到y有那么多个,菜鸡如我还不怎么会可持久化之类的,那就直接排个序什么的然后按顺序做就好,这样听说有7 ...
- 树状数组 && 线段树应用 -- 求逆序数
参考:算法学习(二)——树状数组求逆序数 .线段树或树状数组求逆序数(附例题) 应用树状数组 || 线段树求逆序数是一种很巧妙的技巧,这个技巧的关键在于如何把原来单纯的求区间和操作转换为 求小于等于a ...
- hdu1394(枚举/树状数组/线段树单点更新&区间求和)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意:给出一个循环数组,求其逆序对最少为多少: 思路:对于逆序对: 交换两个相邻数,逆序数 +1 ...
- hdu 1166:敌兵布阵(树状数组 / 线段树,入门练习题)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- hdu 5147 Sequence II【树状数组/线段树】
Sequence IITime Limit: 5000/2500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem ...
- POJ3321[苹果树] 树状数组/线段树 + dfs序
Apple Tree Time Limit: 2000MS Memory Limit: 65536K Total Submissions:39452 Accepted: 11694 Descr ...
- 【poj2182】【poj2828】树状数组/线段树经典模型:逆序查找-空位插入法
poj2182题意:有一个1~n的排列,现在给定每个人前面有多少个人的编号比他大,求这个排列是什么.n<=8000 poj2182题解: 逆序做,可以确定二分最后一个是什么,然后删除这个数.树状 ...
- HDU 5293 Train chain Problem - 树链剖分(树状数组) + 线段树+ 树型dp
传送门 题目大意: 一颗n个点的树,给出m条链,第i条链的权值是\(w_i\),可以选择若干条不相交的链,求最大权值和. 题目分析: 树型dp: dp[u][0]表示不经过u节点,其子树的最优值,dp ...
- [CSP-S模拟测试]:影魔(树状数组+线段树合并)
题目背景 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...
随机推荐
- 误: Apache shutdown unexpectedly解决办法
from:http://www.wopus.org/wordpress-basic/getting-started/2536.htmlXAMPP错 2015年10月20日15:58:19 新手上路发 ...
- PowerDesigner之设置(1)
这里用到的数据库为SQL2000. PowerDesigner 16. 原始格式: (个人认为的缺点) 创建表前先将原来的表删除(创建表逻辑,假如存在则drop.假如原来有数据,用drop就有问题.新 ...
- Farm Tour(最小费用最大流模板)
Farm Tour Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 18150 Accepted: 7023 Descri ...
- JSON工具类库: alibaba/fastjson 使用记录
JSON工具类库: alibaba/fastjson 使用记录 一.了解JSON JSON标准规范中文文档: http://www.json.org/json-zh.html 最佳实践:http:// ...
- sqlserver 脚本和批处理指令小结
一.脚本基础 1.USE语句 设置当前数据库. 2.声明变量 语法:DECLARE @变量名 变量类型 在声明变量后,给变量赋值之 ...
- java读取本地文件
File file = new File("F:/hejing/InstrumentJsonData.txt"); StringBuilder localStrBul ...
- Tomcat 配置连接池
1. Tomcat 配置 JNDI 资源 JNDI(Java Naming and Directory Interface), Java 命名和目录接口; JNDI 作用: 在服务器上配置资源, 然后 ...
- django注册在使用hashlib对密码加密时报Unicode-objects must be encoded before hashing
在使用sh1等hashlib方法进行加密时报:Unicode-objects must be encoded before hashing 解决办法:对要加密的字符串指定编码格式 解决之前: s1=s ...
- 通过Python操作hbase api
# coding=utf-8 # Author: ruin """ discrible: """ from thrift.transport ...
- virt-viewer的简单使用
virt-viewer 简介: virt-viewer是一个用于显示虚拟机的图形控制台的最小工具. 控制台使用VNC或SPICE访问协议. 可以基于其名称,ID或UUID来引用guest虚拟机.如果 ...