[CEOI2010 day2] tower 题解

前言

题目链接:洛谷

题意简述

你要对一个数组排序,满足 \(a_{i + 1} \leq a_i + D\),其中 \(D\) 是给定的常数。求方案数对 \(10^9+9\) 取模的结果。

题目分析

原数组顺序不重要,且我们讨论的东西关于大小比较,考虑先对其排序。考虑使用增量法,把 \(i\) 插到前 \(i - 1\) 个组成的数组里。

如果能插到某一个位置,那么我们不需要考虑它上面那块砖。因为上方要么是空的,要么因为排过序,肯定符合要求。

所以等价于问可以插到哪些砖块的上方。

发现就是询问 \([1, i - 1]\) 有多少个值处在 \([a_i - D, a_i]\) 里面,或者直接放在地上。经典的二维数点问题。或者由于排过序了,双指针即可。

最终答案就是乘法原理,每一步方案数的乘积。

时间复杂度 \(\Theta(n \log n)\),瓶颈在于排序。

代码

略去了快读。

#include <cstdio>
#include <algorithm>
using namespace std;

constexpr const int mod = 1e9 + 9;

int n, D, val[620010];
int res = 1;

signed main() {
	fread(buf, 1, MAX, stdin);
	read(n), read(D);
	for (int i = 1; i <= n; ++i) read(val[i]);
	sort(val + 1, val + n + 1);
	for (int i = 1, j = 1; i <= n; ++i) {
		while (j <= n && val[j] <= val[i] + D) ++j;
		res = 1ll * res * (j - i) % mod;
	}
	printf("%d", res);
	return 0;
}

后记 & 反思

想到插进去了,但是,硬往动态规划的方向靠,导致没想到就是一个乘法原理。

posted @ 2024-07-13 15:55  XuYueming  阅读(3)  评论(0编辑  收藏  举报