一 题目

  QTREE

二 分析

  第一道树链剖分的题,写的好艰难啊。

  题意还是比较好理解的,就是在树上操作。

  对于修改,题中要求的是单点修改,就算是直接树上操作也是非常简单的。

  对于查询,查询的时候,是查询树上一个结点到另一个结点的这条上的最大值。这里就需要用树链剖分了。

  树链剖分,其实就是把树型转换为线型的一种思想。通过剖分一棵树,可以得到很多的链,这些链保证了,树上的相邻节点在链中也一定是相邻的,这样,我们在操作的时候,就可以看做是对链进行更细致的操作了。对链操作时,还要将转换成的线性结构用线段树来维护,单点修改的同时保证快速求出最大值。

  代码可以分为两部分,第一部分是树链剖分部分,第二部分就是线段树了(于普通线段树没有什么区别)。

三 AC代码

  1 #include <bits/stdc++.h>
2
3 using namespace std;
4
5 const int MAXN = 1e5 + 15;
6 int N;
7 int e[MAXN][3];
8 //临接链表建图
9 //双向的!
10 struct Edge
11 {
12 int to, next;
13 }edge[MAXN*2];
14 int head[MAXN], tot;
15
16 int fa[MAXN]; //父节点
17 int size[MAXN]; //以节点为根的子数大小
18 int deep[MAXN]; //深度
19 int son[MAXN]; //重儿子
20 int top[MAXN]; //重链的最高点
21 int p[MAXN]; //结点在整棵树中的编号
22 int fp[MAXN]; //p的反向
23 int pos;
24
25 void init()
26 {
27 tot = 0, pos = 0;
28 memset(head, -1, sizeof(head));
29 memset(son, -1, sizeof(son));
30 }
31
32 void addedge(int u, int v)
33 {
34 edge[tot].to = v;
35 edge[tot].next = head[u];
36 head[u] = tot++;
37 }
38
39 void dfs1(int u, int pre, int d)
40 {
41 deep[u] = d;
42 fa[u] = pre;
43 size[u] = 1;
44 for(int i = head[u]; i != -1; i = edge[i].next)
45 {
46 int v = edge[i].to;
47 //因为建的是双向图
48 if(v != pre)
49 {
50 dfs1(v, u, d+1);
51 size[u] += size[v];
52 if(son[u] == -1 || size[v] > size[son[u]])
53 son[u] = v;
54 }
55 }
56 }
57
58 void dfs2(int u, int sp)
59 {
60 top[u] = sp;
61
62 if(son[u] != -1)
63 {
64 p[u] = pos++;
65 //血的教训把fp写成了fa!!!
66 fp[p[u]] = u;
67 dfs2(son[u], sp);
68 }
69 else
70 {
71 p[u] = pos++;
72 fp[p[u]] = u;
73 return;
74 }
75
76 for(int i = head[u]; i != -1; i = edge[i].next)
77 {
78 int v = edge[i].to;
79 if(v != son[u] && v != fa[u])
80 dfs2(v, v);
81 }
82 }
83
84 struct Node
85 {
86 int l, r, Max;
87 }segTree[MAXN*3];
88
89 void build(int rt, int l, int r)
90 {
91 segTree[rt].l = l;
92 segTree[rt].r = r;
93 segTree[rt].Max = 0;
94 if(l == r) return;
95 int mid = (l + r) >> 1;
96 build(rt<<1, l, mid);
97 build(rt<<1|1, mid + 1, r);
98 }
99
100 void push_up(int rt)
101 {
102 segTree[rt].Max = max(segTree[rt<<1].Max, segTree[rt<<1|1].Max);
103 }
104
105 void update(int rt, int k, int val)
106 {
107 if(segTree[rt].l == segTree[rt].r)
108 {
109 segTree[rt].Max = val;
110 return;
111 }
112 int mid = (segTree[rt].l + segTree[rt].r) >> 1;
113 if(k <= mid)
114 update(rt<<1, k, val);
115 else
116 update(rt<<1|1, k, val);
117 push_up(rt);
118 }
119
120 int query(int rt, int l, int r)
121 {
122 if(segTree[rt].l == l && segTree[rt].r == r)
123 {
124 return segTree[rt].Max;
125 }
126 int mid = (segTree[rt].l + segTree[rt].r) >> 1;
127 if(r <= mid)
128 return query(rt<<1, l, r);
129 else if(l > mid)
130 return query(rt<<1|1, l, r);
131 else
132 {
133 return max(query(rt<<1, l, mid), query(rt<<1|1, mid + 1, r));
134 }
135 }
136
137 int find(int u, int v)
138 {
139 int f1 = top[u], f2 = top[v];
140 int tmp = 0;
141 //保证u的节点编号比v小
142 //且u,v跳到一条链上去
143 while(f1 != f2)
144 {
145 if(deep[f1] < deep[f2])
146 {
147 swap(f1, f2);
148 swap(u, v);
149 }
150 //跳深度深(链更低)的链顶点
151 tmp = max(tmp, query(1, p[f1], p[u]));
152 u = fa[f1];
153 f1 = top[u];
154 }
155 if(u == v) return tmp;
156 if(deep[u] > deep[v]) swap(u, v);
157 return max(tmp, query(1, p[son[u]], p[v]));
158
159 }
160
161
162 int main()
163 {
164 //freopen("input.txt", "r", stdin);
165 int T;
166 scanf("%d", &T);
167 while(T--)
168 {
169
170 init();
171 char op[10];
172 int u, v;
173 scanf("%d", &N);
174 for(int i = 0; i < N-1; i++)
175 {
176 scanf("%d %d %d", &e[i][0], &e[i][1], &e[i][2]);
177 addedge(e[i][0], e[i][1]);
178 addedge(e[i][1], e[i][0]);
179 }
180 dfs1(1, 0, 0);
181 dfs2(1, 1);
182 build(1, 0, pos - 1);
183
184 for(int i = 0; i < N-1; i++)
185 {
186 if(deep[e[i][0]] < deep[e[i][1]])
187 swap(e[i][0], e[i][1]);
188 update(1, p[e[i][0]], e[i][2]);
189 }
190 while(scanf("%s", op) == 1)
191 {
192 if(op[0] == 'D')
193 break;
194 scanf("%d %d", &u, &v);
195 if(op[0] == 'C')
196 update(1, p[e[u-1][0]], v);
197 else
198 printf("%d\n", find(u, v));
199 }
200 }
201 return 0;
202 }

SPOJ QTree【树链剖分】的更多相关文章

  1. SPOJ QTREE 树链剖分

    树链剖分的第一题,易懂,注意这里是边. #include<queue> #include<stack> #include<cmath> #include<cs ...

  2. Spoj Query on a tree SPOJ - QTREE(树链剖分+线段树)

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  3. 【学术篇】SPOJ QTREE 树链剖分

    发现链剖这东西好久不写想一遍写对是有难度的.. 果然是熟能生巧吧.. WC的dalao们都回来了 然后就用WC的毒瘤题荼毒了我们一波, 本来想打个T1 44分暴力 然后好像是特判写挂了还是怎么的就只能 ...

  4. QTREE 树链剖分---模板 spoj QTREE

    <树链剖分及其应用> 一文讲得非常清楚,我一早上就把他学会了并且A了这题的入门题. spoj QTREE 题目: 给出一棵树,有两种操作: 1.修改一条边的边权. 2.询问节点a到b的最大 ...

  5. SPOJ 375 树链剖分 QTREE - Query on a tree

    人生第一道树链剖分的题目,其实树链剖分并不是特别难. 思想就是把树剖成一些轻链和重链,轻链比较少可以直接修改,重链比较长,用线段树去维护. 貌似大家都是从这篇博客上学的. #include <c ...

  6. SPOJ 375 树链剖分

    SPOJ太慢了,SPOJ太慢了, 题意:给定n(n<=10000)个节点的树,每条边有边权,有两种操作:1.修改某条变的边权:2.查询u,v之间路径上的最大边权. 分析:树链剖分入门题,看这里: ...

  7. SPOJ 375 (树链剖分 - 边权剖分 - 修改单边权)

    题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#problem/I 给你一棵有边权的树,有两个操作:一个操作是输出l到 ...

  8. SPOJ 375 (树链剖分+线段树)

    题意:一棵包含N 个结点的树,每条边都有一个权值,要求模拟两种操作:(1)改变某条边的权值,(2)询问U,V 之间的路径中权值最大的边. 思路:最近比赛总是看到有树链剖分的题目,就看了论文,做了这题, ...

  9. SPOJ375.QTREE树链剖分

    题意:一个树,a b c 代表a--b边的权值为c.CHANGE x y  把输入的第x条边的权值改为y,QUERY x y 查询x--y路径上边的权值的最大值. 第一次写树链剖分,其实树链剖分只能说 ...

  10. spoj 375 树链剖分 模板

    QTREE - Query on a tree #tree You are given a tree (an acyclic undirected connected graph) with N no ...

随机推荐

  1. Leetcode(868)-二进制间距

    给定一个正整数 N,找到并返回 N 的二进制表示中两个连续的 1 之间的最长距离. 如果没有两个连续的 1,返回 0 . 示例 1: 输入:22 输出:2 解释: 22 的二进制是 0b10110 . ...

  2. MarkDown(文本编译器)

    MarkDown(一种高效的文本编译器) 推荐使用Typora 点击此处下载 使用方法 1. 首先创建一个文本文件xxx.txt. 2. 然后修改文件后缀为xxx.md.(可以记做玛德...) 3. ...

  3. Mac 外接 Dell 4K 显示器字体模糊解决办法

    Mac 外接 Dell 4K 显示器字体模糊解决办法 mac mini mbp 2020 refs https://zhuanlan.zhihu.com/p/52100804 xgqfrms 2012 ...

  4. WebGL Programming Guide All In One

    WebGL Programming Guide All In One WebGL WebGL Programming Guide All In One Publication date: July 2 ...

  5. illustrating javascript prototype & prototype chain

    illustrating javascript prototype & prototype chain 图解 js 原型和原型链 proto & prototype func; // ...

  6. 同城速递 & 同城跑腿 & 竞品分析

    同城速递 & 同城跑腿 & 竞品分析 toC / toB 闪送 https://www.ishansong.com/ https://www.tianyancha.com/compan ...

  7. macOS & wifi & ip

    macOS & wifi & ip mac show wifi ip # wireless ipconfig getifaddr en1 # ethernet ipconfig get ...

  8. Flutter: redux简单使用

    Pub redux flutter_redux import 'package:flutter/material.dart'; import 'package:redux/redux.dart'; i ...

  9. 人物传记:Mila Fletcher:如何勤于思考抓住关键?

    Mila Fletcher于2007年毕业于耶鲁大学,她是一名真正意义上的法学博士,在校期间获得了马歇尔奖学金,毕业后曾在美国多家知名律师事务所任职,目前就职于星盟全球投资公司,专注于帮助公司和客户提 ...

  10. 新手如何通过内存和NGK DeFi Baccarat进行组合投资?

    区块链市场在2020年迎来了大爆发,资本市场异常火热.无论是内存,还是DeFi,都无疑是这个火爆的区块链市场中的佼佼者.通过投资内存和DeFi,很多投资者都已经获取了非常可观的收益,尝到了资本市场带来 ...