20ZR暑期联赛班 Day 3

原题大赛

过桥

20ZR暑期联赛班 Day 3_第1张图片

可以发现,两个人相遇后都会掉头走,这意味着每个人位置的相对顺序是不变的。

那么运用一个套路,让相遇的两个人穿插而过,那么现在要求排名为任意值的人的位置。

二分套二分即可

while (l <= r) {
	int mid = (l + r) >> 1; // 二分位置
	int rk = upper_bound(rig + 1, rig + nr + 1, mid - t)- rig - 1 + 
	upper_bound(lef + 1, lef + nl + 1, mid - t)- lef - 1; // 分向左和向右求排名
	if (rk >= k) ans = mid, r = mid - 1;
	else l = mid + 1;
}

分组

20ZR暑期联赛班 Day 3_第2张图片
结合 Link 和 Link 可以学到许多与分组有关的 dp 知识。

首先要确定关键字排序,当然是按 s i s_i si 排序了,那么同一组的人的极差就是第一个人和最后加进的人。那么正常的 dp 状态是 f i , j , k f_{i,j,k} fi,j,k 表示前 i i i 个人分成 j j j 组极差和为 k k k 的方案数,但是不能知道哪个组有没有结束,所以 j j j 那一维应该是有 j j j 组没有结束。那么转移为

{ f i + 1 , j + 1 , k − s i +  ⁣ = f i , j , k 作 为 最 小 值 新 开 一 组 f i + 1 , j , k +  ⁣ = f i , j , k × j 随 便 插 入 一 组 f i + 1 , j − 1 , k + s i +  ⁣ = f i , j , k × j 作 为 最 大 值 结 束 一 组 f i + 1 , j , k + = f i + 1 , j , k 作 为 最 小 值 和 最 大 值 新 开 一 组 并 结 束 \begin{cases} f_{i+1,j + 1, k - s_i} +\!= f_{i,j,k} & 作为最小值新开一组 \\ f_{i+1,j,k} +\!= f_{i,j,k} \times j & 随便插入一组 \\ f_{i+1,j-1,k + s_i} +\!= f_{i,j,k} \times j & 作为最大值结束一组 \\ f_{i+1,j,k} += f_{i+1,j,k} & 作为最小值和最大值新开一组并结束 \end{cases} fi+1,j+1,ksi+=fi,j,kfi+1,j,k+=fi,j,k×jfi+1,j1,k+si+=fi,j,k×jfi+1,j,k+=fi+1,j,k便

第四个容易落掉。用滚动数组优化掉第一维,然后这样 dp 还需要一个偏移量防止数组下标出现负数,复杂度为 O ( n 2 × ∑ i S i ) O(n^2 \times \sum_i S_i) O(n2×iSi),会超时。

优化的应该是 k k k 这一维,因为我们求的是极差和 < k <k ,但这个 k k k 有很多想去不掉的冗余状态。那么神仙来了,他用了差分的思想,令 s i = a i − a i − 1 s_{i}=a_{i}-a_{i-1} si=aiai1

a i − a j = a i + 1 − a i + a i + 1 − a i + 2 + a i + 2 − a i + 1 + ⋯ + a j = a j − 1 ⇕ a i − a j = ∑ k = i + 1 j s k a_{i}-a_{j}=a_{i+1} - a_i + a_{i+1} - a_{i+2} + a_{i + 2} - a_{i + 1} + \cdots + a_j = a_{j-1}\\ \Updownarrow \\ a_{i}-a_{j}=\sum_{k=i +1}^{j} s_{k} aiaj=ai+1ai+ai+1ai+2+ai+2ai+1++aj=aj1aiaj=k=i+1jsk

可以发现这个式子在不断增长的,所以只需要转移 k k k 以内的即可。

最大

01 Trie 的板子,有异或、和、或三个情况,会写在这 Link。

你可能感兴趣的:(20ZR暑期联赛班 Day 3)