https://www.lydsy.com/JudgeOnline/problem.php?id=2819

题意:树上单点修改及区间异或和查询。

思维难度不高,但是题比较硬核。

整体思路是维护每一个结点到根节点的距离。查询u,v树链上的异或和就是query(v) ^ query(u) ^ a[lca(u,v)],所以就要想办法维护树上的结点到根节点的异或和。

网上的题解大多是选择直接维护答案,修改的时候修改整颗子树的答案,用线段树或者树状数组区间异或一下l到r内的答案就可以。

我一开始没有想到直接上lca直接维护根节点的距离,所以在dfs序上见了一颗线段树,查询的时候query 1到u第一次出现地方的异或和,区间的时候常规单点修改也可过。

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
inline int read(){int now=;register char c=getchar();for(;!isdigit(c);c=getchar());
for(;isdigit(c);now=now*+c-'',c=getchar());return now;}
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 5e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
LL a[maxn];
struct Edge{
int next,to;
}edge[maxn * ];
int head[maxn],tot;
void init(){
for(int i = ; i <= N ; i ++) head[i] = -;
tot = ;
}
void add(int u,int v){
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot++;
}
const int SP = ;
int pa[maxn][SP],dep[maxn];
//求dfs序
int num;
int dfs_index[maxn * ];
PII pos[maxn];
void dfs(int t,int la){
pa[t][] = la;
dep[t] = dep[la] + ;
for(int i = ; i <= SP - ; i ++) pa[t][i] = pa[pa[t][i - ]][i - ];
pos[t].fi = ++num;
dfs_index[num] = t;
for(int i = head[t]; ~i ; i = edge[i].next){
int v = edge[i].to;
if(v == la) continue;
dfs(v,t);
}
pos[t].se = ++num;
dfs_index[num] = t;
}
int lca(int u,int v){
if(dep[u] < dep[v]) swap(u,v);
int t = dep[u] - dep[v];
for(int i = ; i <= SP - ; i ++){
if(t & ( << i)) u = pa[u][i];
}
for(int i = SP - ; i >= ; i --){
int uu = pa[u][i],vv = pa[v][i];
if(uu != vv){
u = uu;
v = vv;
}
}
return u == v? u :pa[u][];
}
//线段树
struct Tree{
LL sum;
}tree[maxn << ];
void Pushup(int t){
tree[t].sum = tree[t << ].sum ^ tree[t << | ].sum;
}
void Build(int t,int l,int r){
if(l == r){
tree[t].sum = a[dfs_index[l]];
return;
}
int m = (l + r) >> ;
Build(t << ,l,m); Build(t << | ,m + ,r);
Pushup(t);
}
void update(int t,int p,int x,int L,int R){
if(L == R){
tree[t].sum = x;
return;
}
int m = (L + R) >> ;
if(p <= m) update(t << ,p,x,L,m);
else update(t << | ,p,x,m + ,R);
Pushup(t);
}
LL query(int t,int l,int r,int L,int R){
if(l <= L && R <= r){
return tree[t].sum;
}
int m = (L + R) >> ;
if(r <= m) return query(t << ,l,r,L,m);
else if(l > m) return query(t << | ,l,r,m + ,R);
else return query(t << ,l,m,L,m) ^ query(t << | ,m + ,r,m + ,R);
} LL query(int x){
return query(,,pos[x].fi,, * N);
}
int main(){
Sca(N); init();
For(i,,N) Scl(a[i]);
For(i,,N - ){
int u,v; Sca2(u,v);
add(u,v); add(v,u);
}
dfs(,);
Build(,, * N);
Sca(K);
while(K--){
char op[];
int u,v;
scanf("%s%d%d",op,&u,&v);
if(op[] == 'Q'){
if(query(u) ^ query(v) ^ a[lca(u,v)]) puts("Yes");
else puts("No");
}else{
update(,pos[u].fi,v,, * N);
update(,pos[u].se,v,, * N);
a[u] = v;
}
}
return ;
}

bzoj2819 DFS序 + LCA + 线段树的更多相关文章

  1. bzoj3306: 树(dfs序+倍增+线段树)

    比较傻逼的一道题... 显然求子树最小值就是求出dfs序用线段树维护嘛 换根的时候树的形态不会改变,所以我们可以根据相对于根的位置分类讨论. 如果询问的x是根就直接输出整棵树的最小值. 如果询问的x是 ...

  2. Codeforces 877E - Danil and a Part-time Job(dfs序+线段树)

    877E - Danil and a Part-time Job 思路:dfs序+线段树 dfs序:http://blog.csdn.net/qq_24489717/article/details/5 ...

  3. 用dfs序处理线段树的好题吗?

    https://www.cnblogs.com/mountaink/p/9878918.html 分析:每次的选取必须选最优的一条链,那我们考虑一下选择这条链后,把这条路上的点的权值更新掉,再采取选最 ...

  4. 7月13日考试 题解(DFS序+期望+线段树优化建图)

    T1 sign 题目大意:给出一棵 N 个节点的树,求所有起点为叶节点的有向路径,其 上每一条边权值和的和.N<=10000 水题.考试的时候毒瘤出题人(学长orz)把读入顺序改了一下,于是很多 ...

  5. hdu 3974 Assign the task(dfs序上线段树)

    Problem Description There is a company that has N employees(numbered from 1 to N),every employee in ...

  6. Luogu P2982 [USACO10FEB]慢下来 Slowing down | dfs序、线段树

    题目链接 题目大意: 有一棵N个结点树和N头奶牛,一开始所有奶牛都在一号结点,奶牛们将按从编号1到编号N的顺序依次前往自己的目的地,求每头奶牛在去往自己目的地的途中将会经过多少已经有奶牛的结点. 题解 ...

  7. Codeforces Round #200 (Div. 1) D. Water Tree(dfs序加线段树)

    思路: dfs序其实是很水的东西.  和树链剖分一样, 都是对树链的hash. 该题做法是:每次对子树全部赋值为1,对一个点赋值为0,查询子树最小值. 该题需要注意的是:当我们对一棵子树全都赋值为1的 ...

  8. hdu4366 Successor (dfs序+zkw线段树)

    Successor Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  9. URAL 1890 . Money out of Thin Air (dfs序hash + 线段树)

    题目链接: URAL 1890 . Money out of Thin Air 题目描述: 给出一个公司里面上司和下级的附属关系,还有每一个人的工资,然后有两种询问: 1:employee x y z ...

随机推荐

  1. Error: File 'C:\somepath\bin\ARM\Release\App_1.1.218.0_scale-100.appx' not found.

    Hi Everyone, We are working on a fix for this issue as quickly as we can, but we have identified a w ...

  2. Web API 2 添加Models and Controllers Part 2.

    在方案中找到Models文件夹,右键添加类,命名为Author. Author.cs 替换以下代码 C# using System.Collections.Generic; using System. ...

  3. JarvisOJ BASIC 德军的密码

    已知将一个flag以一种加密形式为使用密钥进行加密,使用密钥WELCOMETOCFF加密后密文为 000000000000000000000000000000000000000000000000000 ...

  4. 监听导航新增Tab选项卡-layui

    1. 加载element模块 2. 监听导航事件 3. 创建选项卡 //加载element模块 layui.use('element', function () { element = layui.e ...

  5. java http 伪造请求头

    import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import ...

  6. 数据库管理 trove openstack

    Trove是数据库即服务的OpenStack.它旨在完全基于OpenStack运行,其目标是允许用户快速轻松地利用关系数据库的功能,而无需处理复杂的管理任务.云用户和数据库管理员可以根据需要配置和管理 ...

  7. Cash Machine POJ - 1276 多重背包二进制优化

    题意:多重背包模型  n种物品 每个m个  问背包容量下最多拿多少 这里要用二进制优化不然会超时 #include<iostream> #include<cstdio> #in ...

  8. 洛谷P1622释放囚犯

    题目: 这个题很明显是一个区间DP,但是比较不同的是,这个题它很像区间DP的经典题——石子合并. 然后我傻傻的搞了这个题搞了一下午,然后几乎看遍了全网的题解,就只看懂了这个方法,可能是我太菜了吧,但是 ...

  9. 【AGC013C】Ants on a Circle 弹性碰撞

    题目大意 一个长度为\(lm\)的环上有\(n\)只蚂蚁,告诉你每只蚂蚁的位置和朝向,每只蚂蚁会向前爬,速度为\(1m/s\),两只蚂蚁相遇后都会掉头,问你\(t\)秒后每只蚂蚁的位置. \(n\le ...

  10. Breakable loop in Scratch

    Breakable loop in Scratch https://stackoverflow.com/questions/30682144/breakable-loop-in-scratch Bre ...