单调栈 + 线段树.
首先,若在学校 $A$ 选的课权值和不超过 $A$ 权值总和一半,且在学校 $B$ 选的课权值和也不超过 $B$ 权值一半,显然是不如将 $A$ 的课选完或将 $B$ 的课选完其中之一优的,所以至少要有一所学校选的课权值和超过它权值总和的一半.
先假定在学校 $A$ 选的课权值必须超过其总权值一半,算完后交换两个学校再做一次.
记 $p$ 为 $A$ 中第一个权值前缀和超过总权值一半的位置,则在 $A$ 选的区间必定包含 $p$ ,否则肯定不能超过总权值一半.
此时在学校 $B$ 中选择一个区间 $[l,r]$ ,区间内的点会 ban 掉学校 $A$ 中的一些点,此时在学校 $A$ 的选择方法就是从 $p$ 向两边延伸,直到遇到被 ban 掉的点,中间的点权值和就是在 $A$ 中的最大收益.
枚举 $B$ 中选择的区间右端点 $r$ ,用线段树维护选择每个 $l$ 对应的区间 $[l,r]$ 时 $p$ 能拓展到的最远左右端点.
$r$ 增大 $1$ 时, 每个 $[l,r]$ 会新增同一个被 ban 掉的点,若这个被 ban 掉的点已在 $p$ 能拓展到的区间之外,就不用考虑,于是对 $p$ 的左右端点各维护一个单调栈,每次新增 ban 掉的点时,不断将它能覆盖的点弹出,在线段树上做修改即可.
时间复杂度 $O(n\log n)$ .
1 | //%std |