AT2292 Division into Two

神仙思维题.首先我们令\(A>B;A<B\)时交换.

\(dp_i\)表示\(A\)集合最后选的数是\(i\)的方案数.

\[\therefore dp_i=\sum_{j=l-1}^{r}dp_j \]

此处的\(l,r\)表示\([l-1,r]\)能够放进\(A\)集合且剩下的能够放入\(B\)集合的最长区间.

前缀和优化一下即可.

#include<bits/stdc++.h>
#define il inline
#define rg register
#define gi read<int>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int O = 1e5 + 10;
template<class TT>
il TT read() {
	TT o = 0,fl = 1; char ch = getchar();
	while (!isdigit(ch) && ch != '-') ch = getchar();
	if (ch == '-') fl = -1, ch = getchar();
	while (isdigit(ch)) o = o * 10 + ch - '0', ch = getchar();
	return fl * o;
}
int n = gi(), l, r;
ll dp[O], s[O], sum[O], res, ans, A = read<ll>(), B = read<ll>();
int main() {
	if (A < B) A ^= B ^= A ^= B;
	s[n + 1] = 1ll << 62, s[0] = ~(1ll << 62);
	for (int i = 1; i <= n; ++i) s[i] = read<ll>();
	for (int i = 2; i < n; ++i)
		if (s[i + 1] - s[i - 1] < B)
			return puts("0") & 0;
	dp[0] = sum[0] = 1;
	for (int i = 1; i <= n; ++i) {
		while (r < i && s[i] - s[r + 1] >= A) ++r;
		if (r - l >= 0) dp[i] = (sum[r] -  (l ? sum[l - 1] : 0) + mod) % mod;
		sum[i] = (sum[i - 1] + dp[i]) % mod;
		if (s[i] - s[i - 1] < B) l = i - 1;
	}
	for (int i = n; ~i; --i) {
		(ans += dp[i]) %= mod;
		if (s[i + 1] - s[i] < B) break;
	}
	printf("%lld\n", ans);
	return 0;
}
posted @ 2019-11-05 15:27  wuhan2005  阅读(115)  评论(0编辑  收藏  举报