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)\) 的做法。
启发
- 笛卡尔树上分治!!
- 笛卡尔树上分治时启发式的转移!!!
标签:le,log,min,max,PA2014,分治,mid,Druzyny,P5979 来源: https://www.cnblogs.com/qwq-123/p/16492240.html