树的DFS序
例题:P3459 [POI2007] MEG-Megalopolis
给定一棵
个节点的树,根节点为 ,开始每条边边权为 。有 次操作,每次修改操作使得某条边边权为 ,每次查询操作询问 到某个点的边权和。
数据范围:。
如果从 DFS 序列的角度考虑,将每个节点在 DFS 中的第一个出现位置看作 +1,第二个位置看作 -1,则每次查询相当于查询序列的前缀和,而修改操作相当于对该条边的子节点在 DFS 序列中两次出现的位置做单点更新。
#include <cstdio> #include <vector> using std::vector; const int N = 250005; vector<int> tree[N]; int n, in[N], out[N], idx, bit[N * 2]; char op[5]; int lowbit(int x) { return x & -x; } void update(int x, int d) { while (x <= 2 * n) { bit[x] += d; x += lowbit(x); } } int query(int x) { int res = 0; while (x > 0) { res += bit[x]; x -= lowbit(x); } return res; } void dfs(int u, int fa) { idx++; in[u] = idx; update(idx, 1); for (int v : tree[u]) { if (v == fa) continue; dfs(v, u); } idx++; out[u] = idx; update(idx, -1); } int main() { scanf("%d", &n); for (int i = 1; i < n; i++) { int a, b; scanf("%d%d", &a, &b); tree[a].push_back(b); tree[b].push_back(a); } dfs(1, 0); int m; scanf("%d", &m); for (int i = 1; i <= n + m - 1; i++) { scanf("%s", op); if (op[0] == 'A') { int x, y; scanf("%d%d", &x, &y); int z = in[x] < in[y] ? y : x; update(in[z], -1); update(out[z], 1); } else { int x; scanf("%d", &x); printf("%d\n", query(in[x]) - 1); } } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步