题目描述:
You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are numbered from 1 to N. We define dist(a, b) as the number of edges on the path from node a to node b.
Each node has a color, white or black. All the nodes are black initially.
We will ask you to perfrom some instructions of the following form:
- 0 i : change the color of i-th node(from black to white, or from white to black).
- 1 v : ask for the minimum dist(u, v), node u must be white(u can be equal to v). Obviously, as long as node v is white, the result will always be 0.
给出一棵n结点的树,边权为1,一开始每个点颜色都是黑色。 现有q个询问,每次询问会有两种操作: 1.0 i 改变i的颜色,黑变白,白变黑。 2.1 v 询问与v距离最近的白点,显然,当v颜色为白色时,答案是0。
输入
- In the first line there is an integer N (N <= 100000)
- In the next N-1 lines, the i-th line describes the i-th edge: a line with two integers a b denotes an edge between a and b.
- In the next line, there is an integer Q denotes the number of instructions (Q <= 100000)
- In the next Q lines, each line contains an instruction “0 i” or “1 v”
输出
For each “1 v” operation, print one integer representing its result. If there is no white node in the tree, you should write “-1”.
思路:
这是自己写的第一个动态点分治题。
堆
在每个点上都建立一个可删除堆(手写也可以,像我一样偷懒的话两个系统堆模拟也行,一个记录队列中加入的,一个记录堆中被删除的元素,每次遇到队首相同的元素,就同时弹出即可!)这样每个点都可以(近乎)\(O(1)\)的求出一个点上的答案,不过这样的话,更新的复杂度会直接爆炸!
点分治
动态点分治的用处这时就体现出来了,就只用更新点分治树树根到该点的路径上的所有点即可,复杂度为\(O(logn)\),然后在询问的时候,同理在这条路径上,枚举每一个点,将该点队列上的最大值再加上该点到询问点上的距离的值求出,一路\(min\)上去最后得到的就是答案,复杂度同样为\(O(logn)\),枚举该路径只要从当前点开始在点分治树上跳父亲即可
最后就是求两点之间的路径长度,应该不难,用\(LCA\)法即可,\(lca\)可以直接预处理,用跳重链法等都可以,有
1
dis(x,y)=dep[x]+dep[y]-dep[lca]*2
代码
1 |
|