【手动开栈】【dfs序】【树状数组】【Tarjan】bzoj2819 Nim
考虑树状数组区间修改(只对其子树的答案有影响)点查询,每个点记录的是它到根路径上的权值异或和。
答案时query(L)^query(R)^a[lca]。
这种方法在支持区间加法、减法的树上询问的时候可以避免树链剖分。
可能爆栈,考虑手动开栈。(诶诶Tarjan预处理lca的时候怎么没手动开栈?不要在意^_^)
实际上不会爆的。
#include<cstdio>
#include<stack>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector>
using namespace std;
#define N 500001
typedef pair<int,int> Point;
vector<Point>ask[N];
int n,a[N],b[N],m,ancestor[N];
int en,first[N],next[N<<1],v[N<<1];
int FA[N],rank[N],lcas[N];
void AddEdge(const int &U,const int &V)
{
v[++en]=V;
next[en]=first[U];
first[U]=en;
}
int findroot(int x){return FA[x]==x?x:findroot(FA[x]);}
void Union(int x,int y)
{
int U=findroot(x);
int V=findroot(y);
if(rank[U]<rank[V]) FA[U]=V;
else
{
FA[V]=U;
if(rank[U]==rank[V]) ++rank[U];
}
}
bool vis[N];
void LCA(int U,int Fa)
{
ancestor[U]=U;
for(int i=first[U];i;i=next[i])
if(v[i]!=Fa)
{
LCA(v[i],U);
Union(U,v[i]);
ancestor[findroot(U)]=U;
}
vis[U]=1;
for(int i=0;i<ask[U].size();i++)
if(vis[ask[U][i].first])
lcas[ask[U][i].second]=ancestor[findroot(ask[U][i].first)];
}
stack<int>st;
queue<int>q;
int tot,Ls[N],Rs[N],root=1;
void dfs()
{
st.push(1);
Ls[1]=++tot;
b[1]=a[1];
while(!st.empty())
{
int U=st.top(); bool flag=0;
for(int i=first[U];i;i=next[i])
if(!Ls[v[i]])
{
Ls[v[i]]=++tot;
b[v[i]]=(a[v[i]]^b[U]);
st.push(v[i]);
first[U]=next[i];
flag=1;
break;
}
if(!flag)
{
Rs[U]=tot;
st.pop();
}
}
}
int d[N];
void add_node(int p,const int &v){for(;p<=n;p+=(p&(-p)))d[p]^=v;}
void add_range(const int &L,const int &R,const int &v){add_node(L,v);if(R!=n)add_node(R+1,v);}
int query(int p){int res=0;for(;p;p-=(p&(-p)))res^=d[p];return res;}
int A[N],B[N]; char op[N][2];
int main()
{
int x,y;
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
FA[i]=i;
scanf("%d",&a[i]);
}
for(int i=1;i<n;++i)
{
scanf("%d%d",&x,&y);
AddEdge(x,y);
AddEdge(y,x);
}
scanf("%d",&m);
for(int i=1;i<=m;++i)
{
scanf("%s%d%d",op[i],&A[i],&B[i]);
if(op[i][0]=='Q')
{
ask[A[i]].push_back(make_pair(B[i],i));
ask[B[i]].push_back(make_pair(A[i],i));
}
}
LCA(1,0);
dfs();
for(int i=1;i<=n;++i) add_range(Ls[i],Ls[i],b[i]);
for(int i=1;i<=m;++i)
if(op[i][0]=='Q') puts((query(Ls[A[i]])^query(Ls[B[i]])^a[lcas[i]])?"Yes":"No");
else
{
add_range(Ls[A[i]],Rs[A[i]],a[A[i]]^B[i]);
a[A[i]]=B[i];
}
return 0;
}
【手动开栈】【dfs序】【树状数组】【Tarjan】bzoj2819 Nim的更多相关文章
- [BZOJ1103][POI2007]大都市meg dfs序+树状数组
Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了.不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1..n ...
- 【BZOJ】2819: Nim(树链剖分 / lca+dfs序+树状数组)
题目 传送门:QWQ 分析 先敲了个树链剖分,发现无法AC(其实是自己弱,懒得debug.手写栈) 然后去学了学正解 核心挺好理解的,$ query(a) $是$ a $到根的异或和. 答案就是$ l ...
- 【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树
题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...
- 【bzoj2819】Nim DFS序+树状数组+倍增LCA
题目描述 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...
- NOI 2011 阿狸的打字机 (AC自动机+dfs序+树状数组)
题目大意:略(太长了不好描述) 良心LOJ传送门 先对所有被打印的字符串建一颗Trie树 观察数据范围,并不能每次打印都从头到尾暴力建树,而是每遍历到一个字符就在Trie上插入这个字符,然后记录每次打 ...
- HDU 3887:Counting Offspring(DFS序+树状数组)
http://acm.hdu.edu.cn/showproblem.php?pid=3887 题意:给出一个有根树,问对于每一个节点它的子树中有多少个节点的值是小于它的. 思路:这题和那道苹果树是一样 ...
- HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...
- Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+树状数组
C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...
- BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )
一个串a在b中出现, 那么a是b的某些前缀的后缀, 所以搞出AC自动机, 按fail反向建树, 然后查询(x, y)就是y的子树中有多少是x的前缀. 离线, 对AC自动机DFS一遍, 用dfs序+树状 ...
- 【bzoj3881】[Coci2015]Divljak AC自动机+树链的并+DFS序+树状数组
题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...
随机推荐
- JSONP以及Spring对象MappingJacksonValue的使用方式
什么是JSONP?,以及Spring对象MappingJacksonValue的使用方式 原文: https://blog.csdn.net/weixin_38111957/article/detai ...
- POJ2240:Arbitrage(最长路+正环)
Arbitrage Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 29374 Accepted: 12279 题目链接: ...
- gitlab迁移升级
一.迁移步骤 1.首先安装最新版本gitlab(gitlab7.2安装) 2.停止旧版本gitlab服务 3.将旧的项目文件完整导入新的gitlab bundle exec rake gitlab:i ...
- Hbase写入量大导致region过大无法split问题
最近在线上往hbase导数据,因为hbase写入能力比较强,没有太在意写的问题.让业务方进行历史数据的导入操作,中间发现一个问题,写入速度太快,并且业务数据集中到其中一个region,这个region ...
- Death Note
注:本文系作者原创,但可随意转载. ********************************************************************************** ...
- Join/remove server into/from windows domain PS script
Join server into windows domain PS script $username = "ad-domain\admin" $Password = " ...
- php 计算两个日期的间隔天数
使用php内部自带函数实现 1.使用DateTime::diff 实现计算 参考阅读>>PHP DateTime::diff() 上代码: <?php $start = " ...
- SQL优化单表案例
数据准备: -- 创建数据库 mysql> create database db_index_case; Query OK, row affected (0.00 sec) -- 查看数据库 m ...
- CSS垂直居中小结
1.设置子元素: { ... position :absolute; margin:auto; top:; right:; bottom:; left:; } 2.设置子元素:(height必须是固定 ...
- CSS盒模型之margin解析
原文链接:http://www.jianshu.com/p/ccb534e9b588 文章分为: margin的使用 margin的叠压现象 margin的子债父偿现象 一.margin的使用 HTM ...