LOJ 2707「BalticOI 2015」拔河 / 3.14 校内考试 欢乐感 (happy)

\(2n\) 个人,每个人可以选择站左边或者右边,每边有 \(n\) 个位置,每个人在左边右边都各自有一个想要站的位置,同时每个人都有一个力量值,现在给定一个整数 \(k\),问能否分出两个队,这两边各有 \(n\) 名选手,并且他们站在想站的位置(不能多人站在同一位置),并且双方力量和之差不超过 \(k\)
\(k\le 20n,1\le l_i,r_i\le n,1\le s_i\le 20,n\le 3\times 10^4\)(考试时:\(n \le 8\times 10^4\)\(0.5s\)


  背包 结论 动态规划

  首先,如果一个人想站左边的 \(a_i\) 位置,想站右边的 \(b_i\) 位置,那么我们可以将左部点 \(a_i\) 和右部点 \(b_i\) 连一条边权为力量值的边,然后可以发现,我们的问题转化为将边上的边权分给一侧的点,使得左部右部的点边权之和的差不超过 \(k\)

  然后可以发现结论了:点数是 \(2n\) 的,边数也是 \(2n\) 的,而且如果有一个点没有连边,那么就是 NO,因此,这个图是一个基环树,然后可以简单地画图发现,对于基环树树的部分,边的分配方式是确定的,但是对于环的分配方式,可以有两种选择(顺时针以及逆时针,注意这个环一定是一个偶环)。

  然后对于环的分配方式,我们会有两种选择,设每种选择的值会让左右两边有 \(\Delta\) 的差距,那么我们可以使用背包算出最小差距。

  原题可以直接使用 bitset 进行优化背包然后过去。

  然后考试的时候被卡了,这个考虑一种更加快速的办法,我们背包的值域为 \(2sn\),那么不同的数个数为 \(\sqrt{2sn}\),那么可以直接二进制分组优化多重背包,然后再套一个 bitset 进一步加速,复杂度为 \(\mathcal O(\frac{(2sn)^{\frac{3}{2}}\log n}{\omega})\)

  代码

posted @ 2022-03-16 07:59  Werner_Yin  阅读(46)  评论(0编辑  收藏  举报