主要思路

考虑以 轴为矩形最右侧时,矩形最左侧的取值范围:

  • 对于 轴方向长度 小于 轴方向长度的矩形,若矩形最左侧的合法范围为 ,那么应该有以下限制:
    ,此时矩形 轴方向长度为 ,那么 轴方向的方案数为 ,即 ,那么此时 位置对答案的贡献为:
    的线段数量为 的线段下标累加和为 ,则贡献可简化为:
  • 对于 轴方向长度 大于 轴方向长度的矩形,若矩形最左侧的合法范围为 ,那么应该有以下限制:
    ,此时矩形 轴方向长度为 ,那么 轴方向的方案数为 ,即 ,那么此时 位置对答案的贡献为:
    的线段数量为 的线段下标累加和为 ,则贡献可简化为:

使用双指针即可维护 ,使用前缀和即可 得到 位置的贡献。

核心代码

int MAXN = 100000;

void solve() {
    int n = sc.nextInt(), m = sc.nextInt(), k = sc.nextInt();
    long[] cnt = new long[MAXN + 1], sum = new long[MAXN + 1];
    for (int i = 0; i < n; i++) {
        cnt[sc.nextInt()] = 1;
    }
    long ans = 0;
    for (int i = 1, l1 = 1, r1 = 0, l2 = 1, r2 = 0; i <= MAXN; i++) {
        while (i - l1 + k > m) {
            l1++;
        }
        while (r1 + 1 < i && i - r1 + k > 1) {
            r1++;
        }
        while (i - l2 - k > m) {
            l2++;
        }
        while (r2 + 1 < i && i - r2 - k > 1) {
            r2++;
        }
        if (cnt[i] == 1) {
            sum[i] = i;
            if (l1 <= r1) {
                ans += (cnt[r1] - cnt[l1 - 1]) * (m - k - i + 1) + sum[r1] - sum[l1 - 1];
            }
            if (l2 <= r2) {
                ans += (cnt[r2] - cnt[l2 - 1]) * (m + k - i + 1) + sum[r2] - sum[l2 - 1];
            }
        }
        sum[i] += sum[i - 1];
        cnt[i] += cnt[i - 1];
    }
    out.println(ans);
}