P5979 [PA2014]Druzyny

题面

体育课上,\(n\) 个小朋友排成一行(从 \(1\)\(n\) 编号),老师想把他们分成若干组,每一组都包含编号连续的一段小朋友,每个小朋友属于且仅属于一个组。

\(i\) 个小朋友希望它所在的组的人数不多于 \(d_i\),不少于 \(c_i\),否则他就会不满意。

在所有小朋友都满意的前提下,求可以分成的组的数目的最大值,以及有多少种分组方案能达到最大值。

数据范围:\(n\le 10^6\)

题解

首先肯定有 \(n^2\) dp,设 \(f_i\) 表示只考虑 \(1\sim i\) 小朋友的情况下的最大值和方案,这里定义 \(+\)\(f\) 的运算,有转移:

\[f_i=\sum_{j=1}^{i-1} (f_{j}+1) \;\;\;\;\;\;\;\;\left(\max_{j< k\le i} l_k \le i-j+1\le \min_{j< k\le i}r_k\right) \]

考虑优化这个dp。

首先要注意 \(\le (\min_{j< k\le i}r_k)\) 这个限制是好做的,因为设 \(g_i\) 表示最小的 \(j\) 使 \(j\) 满足限制,那么 \(g_i\) 是单调不降的。

所以我们可以预处理出 \(g_i\) ,那么dp就成了:

\[f_i=\sum_{j=g_i}^{i-1} (f_{j}+1) \;\;\;\;\;\;\;\;\left(\max_{j< k\le i} l_k \le i-j+1\right) \]

因为有 \(\max\) 这种东西,我们可以考虑 cdq分治优化dp,然后就是一个二维偏序,这就是好做的。

所以就有 \(n\log^2 n\) 的做法。但是 \(n=10^6\) ,这还不够优秀。

因为有区间 \(\max\) 的存在,我们可以考虑笛卡尔树分治!这样对于一组 \((l,r,mid)\)\(\forall x\in[l,mid),y\in[mid,r],f_x\rightarrow f_y\) 时,\(\max_{j< k\le i} l_k= l_{mid}\)

但是笛卡尔树分治我们不能保证 \(mid\) 两边的区间大小尽量一致啊,这样怎么保证复杂度?

参考上文,我们知道除了保证大小一致,我们还可以让一次分治 \(x+y\rightarrow x,y\) 的复杂度达到 \(\min(x,y)\) ,那么总复杂度也是 \(n\log n\) 的。

现在考虑一下我们的转移,记 \(k=l_{mid}\)

对于 \(y\in[mid,r]\) ,合法的 \(x\) 的范围是 \([\max(l,g_y),\min(mid-1,y-k)]\)

考虑把 \(\max,\min\) 去掉:

  • \(mid\le g_y\):无合法转移。
  • \(l< g_y<mid\):注意到一个这样的 \(y\) 只会有一次这样的转移。
  • \(g_y\le l\) :现在值要考虑 \(x\le \min(mid-1,x-k)\) ,我们先求出 \(j\le mid−k\) 的所有 \(j\) 的贡献,然后每次随着 \(y\leftarrow y+1\)\(x\) 也会 \(\leftarrow x+1\),所以只会贡献一个新的 \(x\) ,因此直接扫描一遍就可以完成更新。最后如果 \(y\) 没有到 \(r\) ,则还需要整体修改 \([y+1,r]\) 一次。

所以对于操作二和操作三中的整体查询/修改,我们可以通过线段树维护,一次分治只会操作一次,所以是 \(O(n\log n)\) 的,而操作三中的扫描一遍的复杂度是 \(\min(x,y)\) 的,所以这部分也是 \(O(n\log n)\) 的,所以就有 \(O(n\log n)\) 的做法。

启发

  • 笛卡尔树上分治!!
  • 笛卡尔树上分治时启发式的转移!!!
posted @ 2022-07-18 22:22  qwq_123  阅读(50)  评论(0编辑  收藏  举报