AutumnKite's Blog

一个 ZJ 小蒟蒻的博客

比赛地址

ABCD 就不写了。

E - Weights on Vertices and Edges

题意

给定一个 \(N\) 个点 \(M\) 条边的点带权、边带权无向连通图 \(G\),你需要删除一些边,使得对于留下的每条边边权小于等于该边所在连通块的点权之和。

\(N,M\le 10^5\)

题解

考虑一个 \(O(NM)\) 的做法,每次将边权大于当前连通块的边全部删除,然后分治处理每个连通块。

显然这个做法与从大到小判断每条边是否满足条件,不满足则删去的做法是一样的。

注意到一条边若满足条件,那么该条边当前所在的连通块中的任意一条边都不会被删除。

于是用带撤销并查集维护即可。

时间复杂度 \(O(M\log M)\)

代码

F - Jewels

题意

\(N\) 个珠宝,\(K\) 种颜色,第 \(i\) 个珠宝颜色为 \(C_i\),价值为 \(V_i\),保证每种颜色至少出现了两次。

你需要对于每个 \(1\le x\le N\),求出满足以下条件时,选择恰好 \(x\) 个珠宝的最大价值和:

  • 对于选择的任意一个珠宝,存在另一个与它颜色相同的珠宝也被选择。

\(N\le 2\times 10^5\)

题解

对于同种颜色价值最大的两个珠宝,一定会被同时选择。考虑将这样的两个珠宝捆在一起。

我们将所有珠宝按价值从大到小排序,特别地,对于两个捆在一起的珠宝,价值看成平均值,并且价值相等时强制排在其它珠宝前面。

对于一个 \(x\),若前 \(x\) 个珠宝恰好可以被选择,那么答案一定为前 \(x\) 个珠宝的价值和。

否则,我们可以先选择前 \(x-1\) 个,然后考虑如何使数量增加 \(1\)。我们在选择前 \(x-1\) 个的基础上,定义以下集合(一种颜色使用过当且仅当选择的珠宝中存在该颜色的珠宝):

  • \(P\) 为被选择的珠宝中不是捆在一起的珠宝。
  • \(Q\) 为颜色使用过的珠宝中没有被选择的珠宝。
  • \(R\) 为颜色使用过的、捆在一起且其他该颜色的珠宝没有被选择的珠宝对。
  • \(S\) 为颜色没使用过的、捆在一起的珠宝对。
  • \(T\) 为颜色没使用过的、捆在一起的珠宝和其他该颜色的珠宝中价值最大的组成的三元组。

那么有三种情况:

  • 添加一个 \(Q\) 中的珠宝。
  • 删去一个 \(P\) 中的珠宝,添加一个 \(S\) 中的珠宝对。
  • 删去一个 \(R\) 中的珠宝对,添加一个 \(T\) 中的珠宝三元组。

可以证明不可能存在这三种情况以外的调整方法。

于是我们使用 std::multiset 维护即可。

时间复杂度 \(O(N\log N)\)

代码


深深明白自己的弱小

评论

如需要头像服务请在「邮箱」中填写 Gravatar 中绑定的邮箱