Jamie and Tree( Codeforces 916E)
2018-01-24 10:49
429 查看
题意:
给出一个有n个点以及n-1条边的树,进行3个操作:1. 将x变成整个树的根
2. 将以x,y相对于根的最近公共祖先的为根的那棵子树的所有根节点加上z.
3. 查询以x为根的子树的所有节点的和
算法:
LCA,DFS序,线段树区间维护解题思路:
首先考虑不对根进行修改,通过对根与询问节点的相对位置关系分析,通过求LCA实现各个操作。由于每一次操作修改的点不确定,最差情况下暴力修改会达到O(),所以自然而然的考虑线段树维护。然后我们先做好LCA算法的准备工作,以及通过DFS序建立区间更新的线段树。
接着分析每一个操作:
操作1:直接将root标记成x即可。
操作2:仔细分析根和x,y的可能存在位置关系,可能三种情况,分别分析很容易得出求解方法
操作3:通过分析root与x的关系,可以分为x是根与x不是根两种
对于第一种,直接输出所有值就ok了。
对于第二种,又可以分为root在x的子树中和不在x的子树中两种
如果root在x的子树中, 输出x对应的子树的和
如图:
否则:如图
代码:
#include <stdio.h> #include <string.h> #include <iostream> #include <vector> #include <stack> #include <math.h> #define LL long long #define lson ins<<1 #define rson ins<<1|1 #define mid (r+l)/2 using namespace std; const int Max = 1e5 + 100; int data[Max], fa[Max][33], depth[Max], dep, fir[Max], las[Max]; vector<int> edge[Max]; struct Tree { int l, r; LL sum, lazy; void updata(LL x) {//更新点 sum += (r - l + 1) * x; lazy += x; } } tree[Max << 2]; void DFS(int u, int pos) {//为LCA准备顺便求出DFS序用与建树 depth[u] = pos; fir[u] = ++dep; for (int i = 0; i < edge[u].size(); i++) { int v = edge[u][i]; if (fa[u][0] != v) { fa[v][0] = u; DFS(v, pos + 1); } } las[u] = dep; } void make_lca(int n) {//LCA for (int j = 1; j <= 22; j++) { for (int i = 1; i <= n; i++)fa[i][j] = fa[fa[i][j - 1]][j - 1]; } } int lca(int x, int y) {//LCA if (depth[x] < depth[y])swap(x, y); for (int i = 22; i >= 0; i--) { if (depth[fa[x][i]] >= depth[y])x = fa[x][i]; } if (x == y)return x; for (int i = 22; i >= 0; i--) { if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i]; } return fa[x][0]; } int lst(int x, int y) {//使x比y深1级,用于排除y节点,取子树 for (int i = 22; i >= 0; i--)if (depth[fa[x][i]] > depth[y])x = fa[x][i]; return x; } inline void push_down(int ins) {//下传lazy LL lazyval = tree[ins].lazy; if (lazyval) { tree[lson].updata(lazyval); tree[rson].updata(lazyval); tree[ins].lazy = 0; } } inline void push_up(int ins) {//合并子树,更新节点 tree[ins].sum = tree[lson].sum + tree[rson].sum; } inline void build(int l, int r, int ins) {//建树 tree[ins].l = l, tree[ins].r = r, tree[ins].sum = tree[ins].lazy = 0; if (r == l) { tree[ins].sum = 0; } else if (r > l) { build(l, mid, lson); build(mid + 1, r, rson); push_up(ins); } } inline void updata_tree(int ql, int qr, LL x, int ins = 1) {//树的更新 int l = tree[ins].l, r = tree[ins].r; if (ql <= l && r <= qr)tree[ins].updata(x); else { push_down(ins); if (ql <= mid)updata_tree(ql, qr, x, lson); if (qr > mid)updata_tree(ql, qr, x, rson); push_up(ins); } } inline LL query(int ql, int qr, int ins = 1) {//查询 int l = tree[ins].l, r = tree[ins].r; if (ql <= l && r <= qr)return tree[ins].sum; else { push_down(ins); LL res = 0; if (ql <= mid)res += query(ql, qr, lson); if (qr > mid)res += query(ql, qr, rson); return res; } } int main() { int n, m, u, v; scanf("%d%d", &n, &m); for (int a = 1; a <= n; a++)scanf("%d", &data[a]); for (int a = 1; a < n; a++)scanf("%d%d", &u, &v), edge[u].push_back(v), edge[v].push_back(u); int root = 1; DFS(root, 1); make_lca(n); build(1, dep, 1); for (int a = 1; a <= n; a++)updata_tree(fir[a], fir[a], data[a]); while (m--) { int ope, x, y; LL z; scanf("%d", &ope); if (ope == 1)scanf("%d", &x), root = x; else if (ope == 2) { scanf("%d%d%lld", &x, &y, &z); int i = lca(x, y), j = lca(root, i); if (i == j) { int lx = lca(root, x), ly = lca(root, y); updata_tree(1, n, z); if (lx != root && ly != root) { i = lx + ly - i;//i与其中至少一个相等 i = lst(root, i); updata_tree(fir[i], las[i], -z); } } else updata_tree(fir[i], las[i], z); } else { scanf("%d", &x); if (x == root)printf("%lld\n", query(1, n)); else { if (lca(root, x) == x) { x = lst(root, x); printf("%lld\n", query(1, n) - query(fir[x], las[x])); } else printf("%lld\n", query(fir[x], las[x])); } } } return 0; }
相关文章推荐
- 【codeforces 514E】Darth Vader and Tree
- Codeforces 741D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
- Codeforces 764C Timofey and a tree 树+思维
- codeforces 812 E. Sagheer and Apple Tree(树上博弈)
- codeforces 764C Timofey and a tree(树+思维)
- [Ccodeforces 736C] Ostap and Tree - 树形DP
- Codeforces 461 B. Appleman and Tree
- Codeforces 682C Alyona and the Tree【Dfs+YY思维】好题
- Codeforces 741.D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
- Codeforces 375D:Tree and Queries 点化成区间 莫队
- Codeforces 514E Darth Vader and Tree DP + 矩阵快速幂
- CodeForces 题目191C. Fools and Roads(Link Cut Tree,边权加求边权值)
- CodeForces 771C Bear and Tree Jumps 树形DP
- CodeForces-657A-Bear and Forgotten Tree 3
- CodeForces 682C Alyona and the Tree (树+dfs)
- Codeforces 842C Ilya And The Tree(树上DP+因子个数估计)
- codeforces-342E-Xenia and Tree
- 【CodeForces438E】The Child and Binary Tree
- CodeForces 868 E. Policeman and a Tree
- [树上启发式合并 && 哈希] Codeforces 741D. Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths