easy:
做法1.
可以仿照最小生成树的Kruskal做法, 将边权按照从小到大排序
对于每个询问: 按边权从小到大依次连接各个边, 同时用并查集维护特殊点的连通性, 一旦某条边加入后, 遍历所有的特殊点发现它们属于同一集合, 那么答案就是这条边的边权
复杂度:
O(m⋅logm+q⋅m⋅n)
做法2.
对于某个权值
x
, 如果权值不超过
所以二分枚举
x
, 用
复杂度:
O(n⋅logv)
mid:
答案很显然在最小生成树上取到, 这样就将原图转化成了一颗树
其中与hard一个很显然的不同就是: 点数不超过20个
所以只需要暴力求出这20个点两两之间路径上的最大值就好了
对于求: 两点之间树上路径最大值有2个做法:
做法1.
树链剖分 复杂度:
O(log2n)
(我自己提交的树链剖分TLE了, 我本意是: 不卡这个log的)
做法2.
倍增求LCA的同时维护max[i][j]代表: 第i个节点到向上
2j
个节点的路径上的最大值
然后一边求LCA的同时求出到LCA的路径上的最大值, 两个最大值中较大的一个就是答案 复杂度:
O(logn)
所以总的复杂度为:
O(q⋅20⋅logn)
hard:
设定一个常数k
当
p>k
时, 这时候
%p=c
的点不超过k个, 向上面mid一样做就好了, 假设这样的询问有
q1
个, 时间复杂度:
O(q1⋅k⋅logn)
当
p≤k
时, 将答案离线下来并按照p和c从小到大排序, 同时处理出所有p相同且c相同的区间询问
对于同一个
pi
和
ci
,将所有
%pi=ci
的点, 两两(
cj
和
cj+p
)求路径上的最大值, 并将这个相邻最大值更新到线段树上, 对于一个区间询问, 直接从线段树上获得
[l,r]
的区间最值就好了
关于复杂度, 最坏情况就是每一个p和c都不相同, 然而p只有不超过k个
对于某个
pi
,
%pi=0,1,⋯,pi−1
的点一共是n个, 所以每个点只会被更新(或删除)到线段树上一次
假设这样的询问有
q2
个, 复杂度最坏情况:
O(q2⋅k⋅n⋅logn)
当
k=n√
时, 总时间复杂度为:
O(nn√logn)