题目

传送门:QWQ

分析

先敲了个树链剖分,发现无法AC(其实是自己弱,懒得debug、手写栈)

然后去学了学正解

核心挺好理解的,$ query(a) $是$ a $到根的异或和。

答案就是$ lca(x,y) \hat{}  query(x)  \hat{}  query(b) $

接着维护异或和,很显然线段树挺容易搞的。

但我们今天学学树状数组来维护异或和

若将区间$ [l,r] $内的元素全部异或x,相当于在第l位标记x,再在第r+1位标记x,
这样,对于第r位以后的元素,这两个命令互相抵消,查询某个元素的值,只需用树状数组把它之前的命令全部累加起来即可。

强无敌了~~~

代码

lca+dfs序+树状数组:

#include <bits/stdc++.h>
using namespace std;
const int maxn=;
int fa[maxn][],depth[maxn],w[maxn];
int in[maxn],out[maxn],cnt,vis[maxn],n,bit[maxn];
vector<int> G[maxn];
int dfs(int u){
for(int i=;i<;i++){
if(depth[u] < ( << i)) break;
fa[u][i]=fa[fa[u][i-]][i-];
}
in[u]=++cnt;
for(int i=;i<G[u].size();i++){
int v=G[u][i]; if(vis[v]) continue; vis[v]=;
fa[v][]=u; depth[v]=depth[u]+; dfs(v);
} out[u]=cnt;
}
int lca(int x,int y){
if(depth[x]<depth[y]) swap(x,y);
int d=(depth[x]-depth[y]);
for(int i=;i<;i++){
if((<<i) & d) x=fa[x][i];
}
for(int i=;i>=;i--){
if(fa[x][i]!=fa[y][i]){
x=fa[x][i]; y=fa[y][i];
}
}
if(x==y) return x;
else return fa[x][];
}
void add(int x,int v){for(;x<=n;x+=x&-x) bit[x]^=v;}
int query(int x){int ans=;for(;x>;x-=x&-x) ans^=bit[x];return ans;}
int main()
{
int u,v,q;
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&w[i]);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
G[u].push_back(v);G[v].push_back(u);
}
vis[]=;dfs();
for(int i=;i<=n;i++){
add(in[i],w[i]); add(out[i]+,w[i]);
}
scanf("%d",&q);
int a,b; char s[];
while(q--){
scanf("%s%d%d",s,&a,&b);
if(s[]=='Q'){
int ans=w[lca(a,b)]^query(in[a])^query(in[b]);
if(ans!=) puts("Yes");
else puts("No");
// printf("--------------- %d %d %d\n",lca(a,b),query(in[a]),query(in[b]));
}
else{
add(in[a],w[a]);add(out[a]+,w[a]);
w[a]=b;
add(in[a],w[a]);add(out[a]+,w[a]);
}
}
return ;
}
/*
8
1 3 5 2 5 3 1 1
1 5
3 5
2 5
1 4
6 3
7 4
8 3
13
Q 1 2
Q 3 5
Q 1 8
Q 3 5
Q 6 2
C 2 5
C 4 6
C 8 5
Q 1 2
Q 3 5
Q 1 8
Q 3 5
Q 6 2
*/

树链剖分(无法AC):

#include <bits/stdc++.h>
using namespace std;
const int maxn=;
int top[maxn],fa[maxn],son[maxn],dep[maxn],siz[maxn];
int wt[*maxn],w[*maxn],id[*maxn],v[*maxn],cnt,n;
vector<int> G[maxn];
void build(int o,int l,int r){
if(l==r){ v[o]=wt[l]; return; }
int mid=l+r>>;
build(o<<,l,mid); build(o<<|,mid+,r);
v[o]=v[o<<]^v[o<<|];
}
void update(int o,int l,int r,int val,int L){
// printf("--->>> %d %d %d %d %d\n",o,l,r,val,L);
if(l==r){
v[o]=val; return;
}
int mid=l+r>>;
if(L<=mid) update(o<<,l,mid,val,L);
else update(o<<|,mid+,r,val,L);
v[o]=v[o<<]^v[o<<|];
}
int query(int o,int l,int r,int L,int R){
if(l>R||r<L) return ;
if(l>=L&&r<=R){return v[o];}
int mid=l+r>>;
int ans=query(o<<,l,mid,L,R)^query(o<<|,mid+,r,L,R);
return ans;
}
///////////////////////////////////////////
int dfs1(int x,int f,int depth){
dep[x]=depth; fa[x]=f; siz[x]=;
int maxnum=;
for(int i=;i<G[x].size();i++){
int v=G[x][i];
if(v==f) continue;
dfs1(v,x,depth+);
siz[x]+=siz[v];
if(maxnum<siz[v]){
maxnum=siz[v]; son[x]=v;
}
}
}
void dfs2(int x,int topf){
top[x]=topf; id[x]=++cnt; wt[id[x]]=w[x];
if(!son[x]) return;
dfs2(son[x],topf);
for(int i=;i<G[x].size();i++){
int v=G[x][i];
if(v!=son[x]&&v!=fa[x]){
dfs2(v,v);
}
}
}
void debug(){
puts("\ndepth: ");
for(int i=;i<=n;i++) printf("%d ",dep[i]);
puts("\nson: ");
for(int i=;i<=n;i++) printf("%d ",son[i]);
puts("\ntop: ");
for(int i=;i<=n;i++) printf("%d ",top[i]);
}
int Qu(int x,int y){
int ans=;
for(;top[x]!=top[y];){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans^=query(,,n,id[top[x]],id[x]);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ans^=query(,,n,id[x],id[y]);
return ans;
}
int main()
{
// freopen("1.txt","r",stdin); // int __size__=30<<20;
// char *__p__=(char*)malloc(__size__)+__size__;
// __asm__("movl %0, %%esp\n"::"r"(__p__));
int u,v,q;
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d",&w[i]);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
G[u].push_back(v);G[v].push_back(u);
}
dfs1(,,); dfs2(,);
build(,,n);
scanf("%d",&q);
// printf("====== %d\n",query(1,1,n,1,1));
int a,b; char s[];
while(q--){
// printf("========= %d\n",q);
scanf("%s%d%d",s,&a,&b);
if(s[]=='Q'){
int ans=Qu(a,b);
if(ans!=) puts("Yes");
else puts("No");
}
else{
update(,,n,b,id[a]);
}
}
// debug();
return ;
}
/*
8
1 3 5 2 5 3 1 1
1 5
3 5
2 5
1 4
6 3
7 4
8 3
13
Q 1 2
Q 3 5
Q 1 8
Q 3 5
Q 6 2
C 2 5
C 4 6
C 8 5
Q 1 2
Q 3 5
Q 1 8
Q 3 5
Q 6 2
*/

【BZOJ】2819: Nim(树链剖分 / lca+dfs序+树状数组)的更多相关文章

  1. Codeforces Round #200 (Div. 1) D Water Tree 树链剖分 or dfs序

    Water Tree 给出一棵树,有三种操作: 1 x:把以x为子树的节点全部置为1 2 x:把x以及他的所有祖先全部置为0 3 x:询问节点x的值 分析: 昨晚看完题,马上想到直接树链剖分,在记录时 ...

  2. 【bzoj3881】[Coci2015]Divljak AC自动机+树链的并+DFS序+树状数组

    题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...

  3. BZOJ 2243:染色(树链剖分+区间合并线段树)

    [SDOI2011]染色Description给定一棵有n个节点的无根树和m个操作,操作有2类:1.将节点a到节点b路径上所有点都染成颜色c:2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认 ...

  4. BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector

    题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...

  5. 【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...

  6. BZOJ 3083 遥远的国度(树链剖分+LCA)

    Description 描述zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度.当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要z ...

  7. POJ - 2763 Housewife Wind (树链剖分/ LCA+RMQ+树状数组)

    题意:有一棵树,每条边给定初始权值.一个人从s点出发.支持两种操作:修改一条边的权值:求从当前位置到点u的最短路径. 分析:就是在边可以修改的情况下求树上最短路.如果不带修改的话,用RMQ预处理LCA ...

  8. 【树链剖分】【线段树】bzoj3626 [LNOI2014]LCA

    引用题解: http://blog.csdn.net/popoqqq/article/details/38823457 题目大意: 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深 ...

  9. cogs 186. [USACO Oct08] 牧场旅行 树链剖分 LCA

    186. [USACO Oct08] 牧场旅行 ★★☆   输入文件:pwalk.in   输出文件:pwalk.out   逐字节对比时间限制:1 s   内存限制:128 MB n个被自然地编号为 ...

随机推荐

  1. Linux:tee命令详解

    tee tee命令用于将数据重定向到文件,另一方面还可以提供一份重定向数据的副本作为后续命令的stdin,简单的说就是把数据重定向到给定文件和屏幕上. 语法 tee(选项)(参数) 选项 -a:向文件 ...

  2. modprobe lsmod

    modprobe是linux的一个命令,可载入指定的个别模块,或是载入一组相依的模块.modprobe会根据depmod所产生的相依关系,决定要载入哪些模块.若在载入过程中发生错误,在modprobe ...

  3. ajax跨域问题解决方案

    今天来记录一下关于ajax跨域的一些问题.以备不时之需. 跨域 同源策略限制 同源策略阻止从一个域上加载的脚本获取或操作另一个域上的文档属性.也就是说,受到请求的 URL 的域必须与当前 Web 页面 ...

  4. Mysql Innodb 引擎优化 参数(innodb_buffer_pool_size)

    在mysql的学习过程中,要是不把一些基本概率弄的很清楚,难免显得过于不专业. 作用: 这个参数主要作用是缓存innodb表的索引,数据,插入数据时的缓冲 默认值:128M 专用mysql服务器设置的 ...

  5. I.MX6 修改调试串口号(ttymx0 -> ttymxc2)

    I.MX6 修改调试串口号(ttymx0 -> ttymxc2) 一.参考文章: uboot修改默认调试串口ttymxc0 ->ttymxc4(imx53) http://www.xueb ...

  6. Verilog乘法器

    乘法器,不能用乘号直接表示,略坑呀 坑归坑,做还是要做的 思路:首先乘法分为有符号乘与无符号乘,所以建立两个module分别运算有符号与无符号.然后在总module中用case语句判断输出应赋的值. ...

  7. erl_0015 《硝烟中的erlang》 读书笔记002 “为过载做计划”

    为过载做计划 到目前为止,我在实际工作中所碰到最常见的错误,基本上都是节点内存耗尽.而且通常都和过长的消息队列有关37.解决这类问题的方法有很多,不过只有在深入.全面的理解系统后,才能做出正确的选择. ...

  8. Codeforces 954H Path Counting 【DP计数】*

    Codeforces 954H Path Counting LINK 题目大意:给你一棵n层的树,第i层的每个节点有a[i]个儿子节点,然后问你树上的简单路径中长度在1~n*2-2之间的每个有多少条 ...

  9. 神器如 dnSpy,无需源码也能修改 .NET 程序

    dnSpy 是 0xd4d 开发的 .NET 程序调试神器. 说它是神器真的毫不为过!它能在完全没有源码的情况下即时调试程序,甚至还能修改程序!本文讲向大家介绍如何使用 dnSpy 修改 .NET 程 ...

  10. 揭示同步块索引(中):如何获得对象的HashCode

    转自:http://www.cnblogs.com/yuyijq/archive/2009/08/13/1545617.html 题外话:为了尝鲜,也兴冲冲的安装了Win7,不过兴奋之余却郁闷不已,由 ...