CF383C Propagating tree
题目
见链接。
题解
知识点:DFS序,树状数组。
我们需要对子树的不同奇偶层加减,用dfn序可以解决子树问题,但是并不能直接分奇偶。
一种比较麻烦的思路是,将dfn序分成两个序列,一个是偶数层点序,一个是奇数层点序列,处理两个序列对于某个点作为子树根节点时,开始和结束节点,然后就可以用线段树分别处理差分。
但实际上,我们不需要对dfn序分离,只需要用两个完整的dfn序,分别统计对奇偶层的改变,每次修改同时修改两个序列的完整子树的差分,但加减不同即可。
其中,两个序列会出现不应该存在的点,比如对于统计偶数层的dfn序出现的奇数层点,那么直接对一个序列做完整子树的修改,会对它们产生错误的修改,但这是无关紧要的。因为我们查询的是单点权值,只要确定我们查询的那个点的奇偶性,去应该出现他的dfn序里查询即可,不存在的点是无法影响答案的。
如果问题改成求一个子树的权值和,那么这种方法就不行了,第一是没法方便的求出一个子树的权值和,因为奇偶层没有分离;第二是对不存在的点做了错误修改,只能用第一种麻烦的方法。
时间复杂度 \(O(n+m\log n)\)
空间复杂度 \(O(n)\)
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct Graph {
struct edge {
int v, nxt;
};
int idx;
vector<int> h;
vector<edge> e;
Graph(int n = 0, int m = 0) { init(n, m); }
void init(int n, int m) {
idx = 0;
h.assign(n + 1, 0);
e.assign(m + 1, {});
}
void add(int u, int v) {
e[++idx] = { v,h[u] };
h[u] = idx;
}
};
struct T {
int sum;
static T e() { return { 0 }; }
T &operator+=(const T &x) { return sum += x.sum, *this; }
};
template<class T>
struct Fenwick {
int n;
vector<T> node;
public:
Fenwick(int _n = 0) { init(_n); }
void init(int _n) {
n = _n;
node.assign(n + 1, T::e());
}
void update(int x, T val) { for (int i = x;i <= n;i += i & -i) node[i] += val; }
T query(int x) {
T ans = T::e();
for (int i = x;i >= 1;i -= i & -i) ans += node[i];
return ans;
}
};
const int N = 200007;
Graph g;
int a[N];
int dfncnt;
int L[N], R[N], dep[N];
void dfs(int u, int fa) {
L[u] = ++dfncnt;
dep[u] = dep[fa] + 1;
for (int i = g.h[u];i;i = g.e[i].nxt) {
int v = g.e[i].v;
if (v == fa) continue;
dfs(v, u);
}
R[u] = dfncnt;
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m;
cin >> n >> m;
g.init(n, n << 1);
for (int i = 1;i <= n;i++) cin >> a[i];
for (int i = 1;i <= n - 1;i++) {
int u, v;
cin >> u >> v;
g.add(u, v);
g.add(v, u);
}
dfs(1, 0);
Fenwick<T> fw[2] = { Fenwick<T>(n),Fenwick<T>(n) };
while (m--) {
int op, x;
cin >> op >> x;
if (op == 1) {
int val;
cin >> val;
bool odd = dep[x] & 1;
fw[odd].update(L[x], { val });
fw[odd].update(R[x] + 1, { -val });
fw[odd ^ 1].update(L[x], { -val });
fw[odd ^ 1].update(R[x] + 1, { val });
//! 单点查询可以[L,R]区间加,因为不存在的点不会影响答案
//! 但如果求子树权值和,那只能一开始就把dfs序按深度奇偶性分开,用线段树维护,操作很复杂
}
else cout << a[x] + fw[dep[x] & 1].query(L[x]).sum << '\n';
}
return 0;
}
CF383C Propagating tree的更多相关文章
- 「CF383C Propagating tree」
这应该属于一个比较麻烦的数据结构处理树上问题. 题目大意 给出一颗根节点编号为 \(1\) 的树,对于一个节点修改时在它的子树中对于深度奇偶性相同的节点加上这个权值,不同则减去这个值,单点查询. 分析 ...
- CF383C Propagating tree (线段树,欧拉序)
\(tag\)没开够\(WA\)了一发... 求出\(dfs\)序,然后按深度分类更新与查询. #include <iostream> #include <cstdio> #i ...
- 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 ...
- Codeforces Round #225 (Div. 2) E. Propagating tree dfs序+-线段树
题目链接:点击传送 E. Propagating tree time limit per test 2 seconds memory limit per test 256 megabytes inpu ...
- AC日记——Propagating tree Codeforces 383c
C. Propagating tree time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- CodeForces 383C Propagating tree
Propagating tree Time Limit: 2000ms Memory Limit: 262144KB This problem will be judged on CodeForces ...
- 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 ...
- C. Propagating tree
C. Propagating tree time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- 题解 CF383C 【Propagating tree】
这道题明明没有省选难度啊,为什么就成紫题了QAQ 另:在CF上A了但是洛谷Remote Judge玄学爆零. 思路是DFS序+线段树. 首先这道题直观上可以对于每一次修改用DFS暴力O(n),然后对于 ...
- codeforces 383C Propagating tree 线段树
http://codeforces.com/problemset/problem/383/C 题目就是说, 给一棵树,将一个节点的值+val, 那么它的子节点都会-val, 子节点的子节点+val. ...
随机推荐
- 每天学五分钟 Liunx | 有趣的 log
说明:看 systemd log 的时候发现了一段有意思的打印,不太明白为什么会这样,贴出来与朋友们分享,欢迎知道的朋友们说明下,非常感谢. 问题描述:服务启动时,会执行 python 脚本,该脚 ...
- 每天学五分钟 Liunx 0110 | 服务篇:守护进程 systemd
有些进程会在系统上运行较长时间,如前面的 Hello World 程序运行时产生的进程.有些进程运行瞬间就结束了,如执行 ps 命令产生的进程,也有的进程会常驻在内存中,提供相应的服务,这样的进程称为 ...
- Prime Time - 介绍
Prime Time是对timing进行分析 Prime Time使用的是STA方法进行分析 工具会有更新,但是核心内容是不变的 Prime Time(intro to STA) 没有PT工具的时候, ...
- 【PID】初学者的pid,详细的介绍了代码为什么是这样写的
from:Improving the Beginner's PID – Introduction « Project Blog (brettbeauregard.com)
- 【ThreadX-GUIX】Azure RTOS GUIX和Azure RTOS GUIX Studio概述
Azure GUIX嵌入式GUI是Microsoft的高级工业级GUI解决方案,专门针对深度嵌入式,实时和IoT应用程序而设计.Microsoft还提供了名为Azure RTOS GUIX Studi ...
- phpcms : Uncaught Error: [] operator not supported for strings... 的解决方案
打开/phpcms/modules/admin/classes/push_api.class.php,大概在约 141行, $fields_arr = $fields_value = ''; 将它改为 ...
- WebStrom中解决中文乱码——2021050
1.首先将IDE Encoding,Project Encoding和下面的Default Encoding for properties file设置为utf-8 2.在HTML中添加 <me ...
- Oracle12c On 银河麒麟v10SP3 的安装过程
Oracle12c On 银河麒麟的安装过程 学习官网资料 下载最新版的preinstall文件 https://yum.oracle.com/repo/OracleLinux/OL8/appstre ...
- vue3异步组件按需加载和vue2异步组件的按需加载
vue3 按需加载组件 子组件.vue <template> <div> <p>这个组件按需加载</p> <h1>这个组件显示</h1 ...
- Jupyter Notebook支持Go
在执行下列命令之前,请确保你已经安装了Go和Jupyter. gophernotes是针对Jupyter和nteract的Go内核,它可以让你在基于浏览器的笔记本或桌面app上交互式地使用Go.下面介 ...