一些圆环问题

Published: by Creative Commons Licence

  • Tags:

环上连通问题

现在有n个顶点形成一个环,顺时针编号为0,1,,n1,相邻的两个顶点有连边。第i个顶点和i+1顶点的连边权重为wi。现在希望有q个请求,每个请求指定两个顶点。现在要求保留环中总权重最小的一组边的子集,且每个请求中给出的两个顶点之间总是存在至少一条路径。

首先讲一个线段树的做法。很显然我们至少可以删除一条边,我们循环遍历删除的那条边,之后发现环成了一个序列,而每个请求变成了一段区间,我们不能删除被区间覆盖的边,但是能删除所有不被区间覆盖的边。很显然正常做的时间复杂度为O(nq),但是实际上可以发现对于相邻的两条边,删除一条并恢复另外一条,实际上区间的总插入和删除次数是O(q)级别的,因此我们可以用线段树维护,总的时间复杂度为O((n+q)log2n)

下面讲一下更快的O(n+q)做法。思路非常简单,就是我们可以把每个请求视作一段区间(从较小的顶点到较大的顶点),之后记f(i)表示覆盖边(i,i+1)的请求集合。可以发现,如果我们删除边(i,i+1)后,所有出现在f(i)中的请求必须经过(n1,0),而所有未出现在f(i)中的请求可以,不能经过(n1,0)这条边,即一旦选择删除边(i,i+1)后,所有查询的连通方案都由f(i)给定的,并且总是有方案的。如果f(i)f(j),我们不能同时删除边(i,i+1)(j,j+1),因为二者的方案存在冲突。因此我们只需要维护f(i),并按照它们代表的集合分组,找到分组总权最大的那个分组中的边删除即可。维护分组是很有难度的,我们可以用随机化的方式,为每个分组维护多重集合的哈希信息,之后判同就变成了O(1)的整数比较问题。如果使用哈希表来分组,时间复杂度会优化到O(n+q)

环上传递问题

题目1:一个环上有n个人,顺时针编号为1,,n。第i个人持有ai个糖果。你每个回合可以指定某个人,将他手头的一个糖果传递给顺时针下一个人(前提被选人至少有一个糖果)。现在给定b1,,bn,保证a1++an=b1++bn,问至少需要多少个回合,才能使得对于任意1in,第i个人正好持有bi个糖果。

ci表示第i个人向下一位总共传递的糖果数。可以发现bi=aici+ci1。可以发现如果我们令c1=x,那么有ci=xti。而我们需要的回合数为ni=1|xti|。这个问题等价于在数轴t1,,tn上都有一个点,现在要在数轴上选择一个点x,它到所有存在的点的总距离最小。很显然我们选择所有存在的点的中位数就能达到最优。

总的时间复杂度为O(n)。(我们最后不需要排序,使用第k大算法即可)

题目2:一个环上有n个人,顺时针编号为1,,n。第i个人持有ai个糖果。你可以对每个i指定一个0ciai。之后第i个人会向顺时针下一个人传递ci个糖果。设之后第i个人持有的糖果数为bi,要求返回b序列总共有多少不同的可能值,结果对素数p取模。

可以发现如果min(c)>0的时候,我们可以让所有cimin(c)b是不变的。因此我们可以认为min(c)=0

di=cici1。那么有bi=aidi。很显然有多少不同的d序列,就存在多少不同的b序列。

下面我们证明cd序列一一对应。假设两个不同的序列cc,产生相同的d序列。分两种情况讨论:一种是存在i使得,ci=ci,那么由于d相同,可以直接得出c=c。还有一种情况是存在一个i,使得ci=0ci>0,这时候由于d相同,可以得出cic中的最小值,而它不满足min(c)=0

因此我们的答案就变成了存在多少c序列,满足0ciai,且min(c)=0。答案为ni=1(ai+1)ni=1ai

总的时间复杂度为O(n)

环上匹配问题

题目1:给定2n个人,顺时针编号为1,,2n。现在要求让环上的两两拉一条绳子,且绳子之间的交点数最多(重复的交点也要多次统计)。

很显然让ii+n共拉一条绳子,这时候任意两条绳子都有交点,达到理论最大值(n2)

总的时间复杂度为O(n)

题目2:给定2n个人,顺时针编号为1,,2n。现在要求让环上的两两拉一条绳子,且绳子之间的交点数最多(重复的交点也要多次统计)。其中我们已经存在k条绳子,拉第i条绳子的人为aibi

提供一道题目

实际上我们把所有未匹配的人按照顺时针排序后,第i个人和第i+nk个人拉一条绳子即可。

可以发现如果(a,b)(c,d)形成的两条绳子无交点,那么(a,d)(c,b)就一定有交点,且与其它绳子的交点总数是不会减少的。换言之最优解的情况下,未选择的绳子必须两两相交,而这时候只有一个唯一解,就是每个人和对面的人拉绳子。

总的时间复杂度为O(n)