一 题目

  [HAOI2015]树上操作

二 分析

  树链剖分的题,这里主要用到了$dfs$序,这题比较简单的就是不用求$lca$。

  1.和树链剖分一样,先用邻接链表建双向图。

  2.跑两遍$dfs$,其实这题可以不这么写,主要是为了确定树型结构转线型后各节点的编号,以及各个链的$top$,$top$很关键,没有$top$就需要不断找父节点。

  3.建线段树,这里一定一定一定要仔细,写太丑就会调很久。o(╯□╰)o

  4.修改操作和常规线段树没有区别,但修改就需要对链上的$top$节点和父节点不断更新,知道找到根节点就可以了。

三 AC代码

  1 /**************************************************************
2 Problem: 4034
3 User: Dybala21
4 Language: C++
5 Result: Accepted
6 Time:2752 ms
7 Memory:16844 kb
8 ****************************************************************/
9
10 #include <bits/stdc++.h>
11 using namespace std;
12 #define ll long long
13
14 const int MAXN = 1e5 + 14;
15 int n, m;
16 int cost[MAXN];
17 int e[MAXN][2];
18 struct Edge
19 {
20 int to, next;
21 }edge[MAXN*2];
22 int head[MAXN], tot;
23 int fa[MAXN];
24 int p[MAXN];
25 int deep[MAXN];
26 int size[MAXN];
27 int son[MAXN];
28 int top[MAXN];
29 int pos;
30 void init()
31 {
32 tot = 0, pos = 0;
33 memset(head, -1, sizeof(head));
34 memset(son, -1, sizeof(son));
35 }
36 void addedge(int u, int v)
37 {
38 edge[tot].to = v;
39 edge[tot].next = head[u];
40 head[u] = tot++;
41 }
42 void dfs(int u, int pre, int d)
43 {
44 fa[u] = pre;
45 deep[u] = d;
46 size[u] = 1;
47 for(int i = head[u]; i != -1; i = edge[i].next)
48 {
49 int v = edge[i].to;
50 if(v != pre)
51 {
52 dfs(v, u, d+1);
53 size[u] += size[v];
54 if(son[u] == -1 || size[v] > size[son[u]])
55 son[u] = v;
56 }
57 }
58 }
59 void dfs2(int u, int sp)
60 {
61 top[u] = sp;
62
63 if(son[u] != -1)
64 {
65 p[u] = ++pos;
66 dfs2(son[u], sp);
67 }
68 else
69 {
70 p[u] = ++pos;
71 return;
72 }
73
74 for(int i = head[u]; i != -1; i = edge[i].next)
75 {
76 int v = edge[i].to;
77 if(v != son[u] && v != fa[u])
78 dfs2(v, v);
79 }
80 }
81 struct Node
82 {
83 int l, r;
84 ll sum, lazy;;
85 }segTree[MAXN*3];
86 void build(int rt, int l, int r)
87 {
88 segTree[rt].l = l;
89 segTree[rt].r = r;
90 segTree[rt].lazy = 0;
91 segTree[rt].sum = 0;
92 if(l == r)
93 return;
94 int mid = (l + r) >> 1;
95 build(rt<<1, l, mid);
96 build(rt<<1|1, mid + 1, r);
97 }
98 void pushdown(int rt)
99 {
100 if(segTree[rt].l == segTree[rt].r)
101 return;
102 int mid = (segTree[rt].l + segTree[rt].r)>>1;
103 ll t = segTree[rt].lazy;
104 segTree[rt].lazy = 0;
105 segTree[rt<<1].lazy += t;
106 segTree[rt<<1|1].lazy += t;
107 segTree[rt<<1].sum += t*(mid-segTree[rt].l+1);
108 segTree[rt<<1|1].sum += t*(segTree[rt].r-mid);
109 }
110 void update(int rt, int l, int r, ll val)
111 {
112 if(segTree[rt].lazy != 0)
113 pushdown(rt);
114 if(segTree[rt].l == l && segTree[rt].r == r)
115 {
116 segTree[rt].sum += (r-l+1)*val;
117 segTree[rt].lazy += val;
118 return;
119 }
120 int mid = (segTree[rt].l + segTree[rt].r)>>1;
121 if(r <= mid)
122 update(rt<<1, l, r, val);
123 else if(l > mid)
124 update(rt<<1|1, l, r, val);
125 else
126 {
127 update(rt<<1, l, mid, val);
128 update(rt<<1|1, mid + 1, r, val);
129 }
130 segTree[rt].sum = segTree[rt<<1].sum + segTree[rt<<1|1].sum;
131 }
132 ll query(int rt, int l, int r)
133 {
134 if(segTree[rt].lazy)
135 pushdown(rt);
136 if(segTree[rt].l == l && segTree[rt].r == r)
137 return segTree[rt].sum;
138 int mid = (segTree[rt].l + segTree[rt].r)>>1;
139 if(r <= mid)
140 return query(rt<<1, l, r);
141 else if(l > mid)
142 return query(rt<<1|1, l, r);
143 else
144 {
145 ll res = 0;
146 res += query(rt<<1, l, mid);
147 res += query(rt<<1|1, mid+1, r);
148 return res;
149 }
150 }
151 ll query(int x)
152 {
153 ll ans = 0;
154 while(top[x] != 1)
155 {
156 ans += query(1, p[top[x]], p[x]);
157 x = fa[top[x]];
158 }
159 ans += query(1, 1, p[x]);
160 return ans;
161 }
162 int main()
163 {
164 //freopen("in.txt", "r", stdin);
165 //freopen("out.txt", "w", stdout);
166 init();
167 scanf("%d%d", &n, &m);
168 for(int i = 1; i <= n; i++)
169 {
170 scanf("%d", &cost[i]);
171 }
172 for(int i = 0; i < n-1; i++)
173 {
174 scanf("%d%d", &e[i][0], &e[i][1]);
175 addedge(e[i][0], e[i][1]);
176 addedge(e[i][1], e[i][0]);
177 }
178 dfs(1, 0, 0);
179 dfs2(1, 1);
180 build(1, 1, pos);
181 for(int i = 1; i <= n; i++)
182 update(1, p[i], p[i], cost[i]);
183 int op, x, xa;
184 for(int i = 0; i < m; i++)
185 {
186 scanf("%d", &op);
187 if(op == 1)
188 {
189 scanf("%d%d", &x, &xa);
190 update(1, p[x], p[x], xa);
191 }
192 else if(op == 2)
193 {
194 scanf("%d%d", &x, &xa);
195 update(1, p[x], p[x] + size[x] - 1, xa);
196 }
197 else
198 {
199 scanf("%d", &x);
200 printf("%lld\n", query(x) );
201 }
202 }
203 return 0;
204 }
205

BZOJ_4034 [HAOI2015]树上操作 【树链剖分dfs序+线段树】的更多相关文章

  1. BZOJ - 4196 软件包管理器 (树链剖分+dfs序+线段树)

    题目链接 设白色结点为未安装的软件,黑色结点为已安装的软件,则: 安装软件i:输出结点i到根的路径上的白色结点的数量,并把结点i到根的路径染成黑色.复杂度$O(nlog^2n)$ 卸载软件i:输出结点 ...

  2. bzoj 4034 [HAOI2015]树上操作 入栈出栈序+线段树 / 树剖 维护到根距离和

    题目大意 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都 ...

  3. BZOJ 2286 树链剖分+DFS序+虚树+树形DP

    第一次学习虚树,就是把无关的点去掉.S里维护一条链即可. #include <iostream> #include <cstring> #include <cstdio& ...

  4. BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector

    题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...

  5. BZOJ 2243:染色(树链剖分+区间合并线段树)

    [SDOI2011]染色Description给定一棵有n个节点的无根树和m个操作,操作有2类:1.将节点a到节点b路径上所有点都染成颜色c:2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认 ...

  6. BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

  7. [BZOJ - 2819] Nim 【树链剖分 / DFS序】

    题目链接: BZOJ - 2819 题目分析 我们知道,单纯的 Nim 的必胜状态是,各堆石子的数量异或和不为 0 .那么这道题其实就是要求求出树上的两点之间的路径的异或和.要求支持单点修改. 方法一 ...

  8. POJ 2763 Housewife Wind 【树链剖分】+【线段树】

    <题目链接> 题目大意: 给定一棵无向树,这棵树的有边权,这棵树的边的序号完全由输入边的序号决定.给你一个人的起点,进行两次操作: 一:该人从起点走到指定点,问你这段路径的边权总和是多少. ...

  9. 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

    题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...

随机推荐

  1. VScode 配置c++环境

    参考 https://code.visualstudio.com/docs/cpp/config-mingw https://zhuanlan.zhihu.com/p/77645306 主要 http ...

  2. Linux 驱动框架---net驱动框架

    这一篇主要是学习网络设备驱动框架性的东西具体的实例分析可以参考Linux 驱动框架---dm9000分析 .Linux 对于网络设备的驱动的定义分了四层分别是网络接口层对上是IP,ARP等网络协议,因 ...

  3. Spring配置声明式事务

    Spring的事务有两种配置,一种是编程式,另一种是声明式,这里我们配置的是声明式事务 <?xml version="1.0" encoding="UTF-8&qu ...

  4. uni-app 支持第三方 H5 离线包

    uni-app 支持第三方 H5 离线包 https://uniapp.dcloud.io/ https://github.com/dcloudio/uni-app refs xgqfrms 2012 ...

  5. css scroll text without wrap & webkit-scrollbar

    css scroll text without wrap hidden webkit-scrollbar .tabs-title-box::-webkit-scrollbar, .tabs-conte ...

  6. 23 种设计模式 APP & 23 Design Patterns App

    23 种设计模式 APP & 23 Design Patterns App https://github.com/xgqfrms/23-design-patterns-app https:// ...

  7. 电信悦 me 智能网关

    电信悦 me 智能网关 悦 me 智能网关 Q1:什么是电信悦 me 智能网关? 悦me网关是智慧家庭的核心终端,作为"光猫+智能路由器"的集合体, 采用了全新的硬件.外观及智能操 ...

  8. npm & cli & node.js

    npm & cli & node.js https://www.npmjs.com/ https://www.npmjs.com/settings/xgqfrms/packages h ...

  9. DevOps tools

    DevOps tools mozart & ansible https://www.ansible.com/integrations/devops-tools websocket jenken ...

  10. DBA 的效率加速器——CloudQuery v1.3.2 上线!

    嘿,兄弟,我们好久不见,你在哪里 嘿,朋友,如果真的是你,请打声招呼 我说好久不见,你去哪里 你却对我说,我去江湖 我去看 CloudQuery v1.3.2,看看新增了哪些好用的小功能! 一.自动/ ...