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)

328

被折叠的 条评论
为什么被折叠?



