(Analysis by Eva Zhu)

$O(2^n \cdot n)$ solution:

Go through all possible subsets and check if every camper has a coach within $D$ units to the left.

$O(n^2)$ solution:

$dp_{i,j}$: we are at $i$, $j$ is the last coach that got chosen.

If $i$ is a coach: $dp_{i,j}$ = $dp_{i-1,j-1}$ + $dp_{i-1,j-2}$ + $\ldots$ + $dp_{i-1,0}$

If $i$ is a camper: $dp_{i,j}$ = $dp_{i-1,j} \cdot$ (1 + ($dis(i, j) \leq D$))

Eva's code:

#include <bits/stdc++.h>
#define ll long long
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, b, a) for(int i = (b); i >= (a); i--)
using namespace std;
const int N = 1e6 + 5, MOD = 1e9 + 7;
ll D, p[N], dp[N], ndp[N], total;
int n, o[N];
int main() {
    scanf("%d%lld", &n, &D);
    rep(i, 1, n) scanf("%lld%d", &p[i], &o[i]);
    dp[0] = 1;
    rep(i, 1, n) dp[i] = 0;
    rep(i, 1, n) {
        rep(j, 0, i) ndp[j] = 0;
        if (o[i] == 1) {
            ll sum = 0;
            rep(j, 0, i-1) sum = (sum + dp[j]) % MOD;
            rep(j, 0, i-1) ndp[j] = dp[j];
            ndp[i] = sum;
        } 
        else {
            rep(j, 0, i - 1) {
                ll val = dp[j];
                if (j > 0 && p[i] - p[j] <= D) {
                    val = (val * 2) % MOD;
                }
                ndp[j] = val;
            }
            ndp[i] = 0;
        }
        rep(j, 0, i) dp[j] = ndp[j];
    }
    rep(j, 0, n) total = (total + dp[j]) % MOD;
    printf("%lld\n", (total - 1 + MOD) % MOD);
    return 0;
}

$O(n)$ solution:

For a camper at index $i$ to be selectable, we need some selected coach in positions $[p_i-D, p_i)$. Only the rightmost coach among these matters, so states should be about rightmost coaches.

Let $f_j$ be the number of good subsets (within the processed prefix) whose rightmost selected coach is exactly $j$.

If current $i$ is a camper: For all eligible coach-states $c$ in range, $f_c$ doubles (choose or not choose this camper); other $f_c$ remain the same.

If current $i$ is a coach: $f_i$ = $TOTAL$ (all possible subsets until now since $i$ can be chosen or not). An $O(n\log n)$ solution would be using a segment tree to maintain this. However, we can also use a queue to maintain a sliding window and get an $O(n)$ solution.

Maintain a queue of the current active coaches. Maintain $mul$ which starts with $1$.

Every time, instead of doubling all the $f$ for current active coaches, let $mul \mathrel{*}= 2$.

Maintain an array $g$, such that $f_i$ = $g_i \cdot mul$. Also maintain the sum of $g$.

To conclude, we maintain:

$mul$ representing the "lazy tag" for the current queue.

$fsum$ = sum of $f_i$ for coaches already popped (inactive; never changes again).

$gsum$ = sum of $g_i$ for coaches still active.

$s$ = $gsum \cdot mul$

$TOTAL$ = $1$ (empty) + $fsum$ + $s$

Eva's code:

#include <bits/stdc++.h>
#define ll long long
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, b, a) for(int i = (b); i >= (a); i--)
using namespace std;
const int N = 1e6 + 5, MOD = 1e9 + 7;
ll p, D, inv2 = (MOD + 1) / 2, qp[N], qg[N];
int main() {
    int n; scanf("%d%lld", &n, &D);
    ll mul = 1, inv_mul = 1, fsum = 0, gsum = 0;
    int headp = 1, tailp = 0;
    int headg = 1, tailg = 0;
    rep(i, 1, n){
        int o; scanf("%lld%d", &p, &o);
        while(headp <= tailp && qp[headp] < p-D){
            fsum = (fsum + (qg[headg] * mul)) % MOD;
            gsum = (gsum - qg[headg]) % MOD;
            headp++, headg++;
        }
        if(o == 0){
            mul = (mul * 2) % MOD;
            inv_mul = (inv_mul * inv2) % MOD;
        } 
        else{
            ll total = (1 + fsum + gsum * mul % MOD) % MOD;
            ll x = (total * inv_mul) % MOD;
            qp[++tailp] = p, qg[++tailg] = x;
            gsum = (gsum + x) % MOD;
        }
    }
    ll ans = (fsum + (gsum * mul) % MOD) % MOD;
    printf("%lld\n", (ans + MOD) % MOD);
    return 0;
}