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;
}