题目链接:
题目大意:给出一张$n$个点$m$条边的无向图,点和边可重复经过,一个狼人初始为人形,有$q$次询问,每次询问要求人形态只能处于编号不小于$L$的点,狼形态只能处于编号不大于$R$的点,询问能否从$S$处于人形态然后在编号在$[L,R]$内的点变身一次成为狼人然后到达 $E$。
题目中编号都是从0开始,太不舒服了,我们按编号从1开始讲QAQ。
题目大意就是询问每次从一个点开始走只能走编号在[l,n]中的点,在任意点变成狼,之后只能走[0,r]中的点,是否能到达另一个点。
后一部分其实就是找有哪些点只走[0,r]中的点能到达终点,那么反过来看,就是终点只走[0,r]中的点能到达哪些点。
那么只要起点能到达的点和终点能到达的点中有交集就有解。
因为起点只能走一些编号较大的点,那么我们求出原图的最大生成树,建出kruskal重构树,求出重构树的dfs序,每次询问在重构树上倍增找能到达的联通块在dfs序上的区间就好了。
相反,从终点走就求出原图的最小生成树,然后也按上述方法找。
找到两段dfs序区间后只要这两段区间中有相同点就能判有解。
我们将每个点在第一个dfs序中的位置作为横坐标,在第二个dfs序中的位置作为纵坐标,剩下的就是一个简单的二维数点问题了。
等会,上面是不是差点什么?原图没有边权啊?
我们以最大生成树为例,对于一条边(x,y),两个点能否通过这条边互相到达,由这两个点中较小的点决定,因此求最大生成树时每条边边权就是边两端点中较小的那个。最小生成树边权就是两端点中较大的那个。
整体思路就是分别建出原图最小生成树和最大生成树的重构树,分别求出每个点在两个重构树中的dfs序位置,然后可持久化线段树二维数点。
kruskal重构树在这里就不赘述了,如果不是太了解可以参考我的另一篇博客,那道题和这道题思想很像。
题面似乎没说保证整张图联通,因此可能是kruskal重构森林。
#include"werewolf.h"#include