一 题目

  [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. 1.rabbitmq 集群安装及负载均衡设置

    标题 : 1.rabbitmq 集群安装及负载均衡设置 目录 : RabbitMQ 序号 : 1 vim /etc/pam.d/login #对于64位系统,在文件中添加如下行 session req ...

  2. zzuli-2259 matrix

    题目描述 在麦克雷的面前有N个数,以及一个R*C的矩阵.现在他的任务是从N个数中取出 R*C 个,并填入这个矩阵中.矩阵每一行的法值为本行最大值与最小值的差,而整个矩阵的法值为每一行的法值的最大值.现 ...

  3. codeforces 6E (非原创)

    E. Exposition time limit per test 1.5 seconds memory limit per test 64 megabytes input standard inpu ...

  4. js replace all

    js replace all https://stackoverflow.com/questions/1144783/how-can-i-replace-all-occurrences-of-a-st ...

  5. 小程序 in action

    小程序 in action https://github.com/xgqfrms/xcx-taro taro https://taro-docs.jd.com/taro/docs/README.htm ...

  6. moment.js 时间格式转换

    moment.js 时间格式转换 moment.js 时间转化 bug 格式错误 bug 02:00 => 14:00 format HH 与 hh HH === 24 小时制 hh === 1 ...

  7. js add Struct to ArrayBuffer

    使用struct-buffer为ArrayBuffer添加结构体 $ npm i struct-buffer 1. 创建结构体 import { DWORD, string_t, StructBuff ...

  8. NLog整合Exceptionless

    前言 在实际的.Net Core相关项目开发中,很多人都会把NLog作为日志框架的首选,主要是源于它的强大和它的扩展性.同时很多时候我们需要集中式的采集日志,这时候仅仅使用NLog是不够的,NLog主 ...

  9. [Python学习笔记]爬虫

    要使用Python 抓取网页,首先我们要学习下面四个模块: 包 作用 webbrowser 打开浏览器获取指定页面: requests 从因特网下载文件和网页: Beautiful Soup 解析HT ...

  10. 修改yapf中的列宽限制值

    yapf是一款由Google开源的Python代码自动格式化工具,它根据PEP 8规范可以帮我们自动格式化我们的代码,让代码更规范.更漂亮.但是其中最大列宽被限制为80,如果超过80,在格式化时就会被 ...