BZOJ_4034 [HAOI2015]树上操作 【树链剖分dfs序+线段树】
一 题目
二 分析
树链剖分的题,这里主要用到了$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序+线段树】的更多相关文章
- BZOJ - 4196 软件包管理器 (树链剖分+dfs序+线段树)
题目链接 设白色结点为未安装的软件,黑色结点为已安装的软件,则: 安装软件i:输出结点i到根的路径上的白色结点的数量,并把结点i到根的路径染成黑色.复杂度$O(nlog^2n)$ 卸载软件i:输出结点 ...
- bzoj 4034 [HAOI2015]树上操作 入栈出栈序+线段树 / 树剖 维护到根距离和
题目大意 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都 ...
- BZOJ 2286 树链剖分+DFS序+虚树+树形DP
第一次学习虚树,就是把无关的点去掉.S里维护一条链即可. #include <iostream> #include <cstring> #include <cstdio& ...
- BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector
题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...
- BZOJ 2243:染色(树链剖分+区间合并线段树)
[SDOI2011]染色Description给定一棵有n个节点的无根树和m个操作,操作有2类:1.将节点a到节点b路径上所有点都染成颜色c:2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认 ...
- BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...
- [BZOJ - 2819] Nim 【树链剖分 / DFS序】
题目链接: BZOJ - 2819 题目分析 我们知道,单纯的 Nim 的必胜状态是,各堆石子的数量异或和不为 0 .那么这道题其实就是要求求出树上的两点之间的路径的异或和.要求支持单点修改. 方法一 ...
- POJ 2763 Housewife Wind 【树链剖分】+【线段树】
<题目链接> 题目大意: 给定一棵无向树,这棵树的有边权,这棵树的边的序号完全由输入边的序号决定.给你一个人的起点,进行两次操作: 一:该人从起点走到指定点,问你这段路径的边权总和是多少. ...
- 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树
题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...
随机推荐
- vue-router离开当前页面提示未保存,解决在使用beforeRouteLeave弹窗多次闪现问题
在使用beforeRouteLeave时要注意两点: 1. next(false)阻止路由继续进行,若不先阻止,会多次执行守卫中的代码 2. 利用setTimeout延时触发弹窗,避免出现闪现情况
- redis运维与开发笔记
- 银河麒麟V10安装ASP.NET Core并配置Supervisor让网站开机自动运行
银河麒麟高级服务器操作系统V10是针对企业级关键业务,适应虚拟化.云计算.大数据.工业互联网时代对主机系统可靠性.安全性.性能.扩展性和实时性的需求,依据CMMI 5级标准研制的提供内生安全.云原生支 ...
- Community Cloud零基础学习(五)Topic(主题)管理
我们以前讲过 Service Cloud 零基础(三)Knowledge浅谈,我们日常可以看见很多得文章或者帖子,我们可以将其通过data category / group进行管理.但是一个系统中得文 ...
- HTTP/HTTPS Proxy & Charles
HTTP/HTTPS Proxy & Charles Charles https://www.charlesproxy.com/ https://www.jianshu.com/p/53d2c ...
- Travis CI in Action
Travis CI in Action node.js https://docs.travis-ci.com/user/tutorial/ https://docs.travis-ci.com/use ...
- fetch & form-data & upload & image file
fetch & form-data & upload & image file no need multipart/form-data https://blog.xinshan ...
- better-scroll使用参考
************better-scroll是基于父元素固定高度,溢出才滚动的,所以父元素务必定高,否则无法滚动***************************************** ...
- NGK公链:夯实基础设施 实现产业大规模应用
当前,区块链已经成为全球技术角逐的前沿,大国及科技巨头竞相在该领域布局,引导区块链服务实体经济,激发市场经济活力.据市场相关研究机构预测,2020年,基于区块链的业务将达到1000亿美元. 对于区块链 ...
- 发布Jar包到maven中央仓库
什么是maven中央仓库 maven是java世界最流行的构建工具,构建内容囊括了一个java项目的整个生命周期.其中最重要的功能就是依赖管理,maven通过一个类似云的ftp站点统一管理所有java ...