【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模拟测试]:影魔(树状数组+线段树合并)
题目背景 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...
随机推荐
- Partial Sum
Partial Sum Accepted : 80 Submit : 353 Time Limit : 3000 MS Memory Limit : 65536 KB Partial Sum ...
- Mybatis+MySql 一个标签中执行多条sql语句 这个坑 ,我心中有一句MMP
解决办法 转自网友: 亲测 解决了问题@ MySql默认是不支持这种骚操作的,但是并不代表不能实现,只需要在jdbc的配置文件中稍做配置: driver=com.mysql.jdbc.Driverur ...
- 密码硬编码(Password Management: Hardcoded Password)
在对项目进行安全扫描时,发现一些密码硬编码问题,本文主要三个方面:1)什么是密码硬编码:2)密码硬编码的危害:3)密码硬编码的解决方案. 一 什么是密码硬编码 将密码以明文的形式直接写到代码中,就是密 ...
- MariaDB数据库主从复制实现步骤
一.MariaDB简介 MariaDB数据库的主从复制方案,是其自带的功能,并且主从复制并不是复制磁盘上的数据库文件,而是通过binlog日志复制到需要同步的从服务器上. MariaDB数据库支持单向 ...
- Android学习资源网站大全
https://github.com/zhujun2730/Android-Learning-Resources 整理了一些 Android 的博客链接.学习资源网站.站在巨人的肩膀上,会看得更远.整 ...
- 剑指offer 面试48题
面试48题:题目:最长不含重复字符的子字符串 题:请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长字符串的长度.假设字符串中只包含‘a’-‘z’的字符.例如,在字符串“arabcacfr ...
- 【整理学习Hadoop】Hadoop学习基础之二:分布式
分布式系统就是将系统的应用层,数据层或其它部分构架成分布(物理和逻辑上的都可以)状(通常是网状).分布式系统通常是为了增强系统的可扩展性.稳定性和执行效率.比如在线游戏通常就是分布系统,里面所谓的 ...
- CSS素材+特效
1.字体:https://www.zhihu.com/question/19680724 2.loading特效:http://www.cnblogs.com/lhb25/archive/2013/1 ...
- Hibernate Student_Course_Score设计
示例: 设计代码,实现在数据库中建student表.course表.和score表,展现三者关系 student表:id.name course表:id.name score表:id.score.st ...
- windows通过ftp下载linux文件
# windows 下载 linux的文件>> ftp <domain_or_ip>>> <input_username>>> <in ...