912 字
5 分钟
题解 CF2211F Learning Binary Search
2026-04-24
无标签

前置#

二分搜索树#

把二分搜索的过程建成一棵二叉树即可. 此时每个节点对应唯一一个点mid, 也可以认为每个节点对应唯一一个二分搜索区间[l, r]. 二分搜索树共有n个节点.

范德蒙德恒等式#

见”组合数学”板块. 我们有

i=0N(x+ix)(y+Niy)=(x+y+N+1x+y+1).\sum_{i = 0}^N \binom{x + i}{x}\binom{y + N - i}{y} = \binom{x + y + N + 1}{x + y + 1}.

曲棍球棒#

i=0N(x+ix)=(x+N+1x+1)\sum_{i = 0}^N \binom{x + i}{x} = \binom{x + N + 1}{x + 1}

题意#

给定一个函数如下:

function f(a, k, l, r):
if a does not contain k:
return 0
mid = floor((l+r) / 2)
if a[mid]==k:
return 1
else if a[mid]<k:
return 1+f(a, k, mid+1, r)
else:
return 1+f(a, k, l, mid-1)

对于所有的单调不减的且1aim1\le a_i \le m的序列aa1km1\le k \le m, 求和, 模676,767,677676, 767, 677.

解法#

求和对象的改变#

容易发现, 该函数即为二分搜索找到kk的次数. 所以我们可以建立二分搜索树, 对于每个节点, 考虑有多少个(a,k)(a, k)使得搜索在此处停止, 再乘以该节点的深度即可.

注意点1#

注意到[l,r][l, r]会被访问, 当且仅当原数组中所有k都被包含在[l,r][l, r]中. 证明好证, 主要是难想到. 因为如果k被分割成两段, 那在分割点就已经返回了, 不会到下面. 同时, 注意到搜索在[l,r][l, r]处停止, 当且仅当amid=ka_{mid} = k. 也就是说, 当数组中kk占据的区间为[x,y][x, y]时, 要求lxyrl \le x\le y\le rmid[x,y]mid\in [x, y].

考虑容斥原理#

先考虑mid[x,y]mid\in [x, y]这个条件, 实际上要求amid=ka_{mid} = k. 他的种类数是(1)

(mid+k2k1)(nmid+mkmk)\binom{mid + k - 2}{k - 1}\binom{n - mid + m - k}{m - k}

如果l1l\ne 1, 我们需要减去l<xl < x的情况, 由于mid处已经是k了, l<xl < x的情况说明al1=ka_{l - 1} = kamid=ka_{mid} = k. 这种情况的种类数是(2):

((l2)+k1k1)(nmid+mkmk)\binom{(l - 2) + k - 1}{k - 1}\binom{n - mid + m - k}{m - k}

rnr \ne n时, 右边同理(3):

(mid+k2k1)((nr1)+mkmk)\binom{mid + k - 2}{k - 1}\binom{(n - r - 1) + m - k}{m - k}

如果l1l\ne 1rnr\ne n, 我们还需要加上(4):

(l+k3k1)(nr+mk1mk)\binom{l + k - 3}{k - 1}\binom{n - r + m - k - 1}{m - k}

利用范德蒙德卷积进行变换#

我们考虑对于所有的k[1,m]k\in [1, m]对上述式子求和. 利用范德蒙德卷积

i=0N(x+ix)(y+Niy)=(x+y+N+1x+y+1)\sum_{i = 0}^{N}\binom{x + i}{x}\binom{y + N - i}{y} = \binom{x + y + N + 1}{x + y + 1}

(1)式为:

(n+m1m1)\binom{n + m - 1}{m - 1}

(2)式为:

(l+n+mmid2m1)\binom{l + n + m - mid - 2}{m - 1}

(3)式为:

(mid+n+mr2m1)\binom{mid + n + m - r - 2}{m - 1}

(4)式为:

(l+n+mr3m1)\binom{l + n + m - r - 3}{m - 1}

最后, 对于每个节点使用容斥统计即可.

代码#

提交记录

void solution() {
/* code here */
ll n, m;
cin >> n >> m;
mint ret = 0;
auto dfs = [&](auto&& self, ll l, ll r, int d) -> void {
if (l > r) {
return;
}
ll mid = (l + r) / 2;
ret += f.nCr(n + m - 1, m - 1) * d;
if (l == 1 && r == n) {
// mid - 1个位置填 [1, k]
// n - mid个位置填 [k, m]
} else if (l == 1) {
ret -= f.nCr(mid + n - r + m - 2, m - 1) * d;
} else if (r == n) {
ret -= f.nCr(l - 2 + n - mid + m, m - 1) * d;
} else {
ret -= f.nCr(l - 2 + n - mid + m, m - 1) * d;
ret -= f.nCr(mid + n - r + m - 2, m - 1) * d;
ret += f.nCr(l + n - r + m - 3, m - 1) * d;
}
self(self, l, mid - 1, d + 1);
self(self, mid + 1, r, d + 1);
};
dfs(dfs, 1, n, 1);
cout << ret.val << '\n';
}
题解 CF2211F Learning Binary Search
https://fuwari.vercel.app/posts/题解-cf2211f-learning-binary-search/
作者
ykindred
发布于
2026-04-24
许可协议
CC BY-NC-SA 4.0