ABC222 D - Between Two Arrays(dp)

目录

Description

有两个不降数组,其中 \(a_i<=b_i\), 求有多少个不降数组 \(c\) 满足 \(a_i<=c_i<=b_i\)

State

\(1<=n<=3000\)

\(0<=a_i<=b_i<=3000\)

Input

2
1 1
2 3

Output

5

Solution

由题意可以写出方程 \(dp[i][j]=dp[i-1][1...j]\) 表示到 \(i\) 位置以 \(j\) 结尾的数组有多少个

但是这样转移时间上为 \(O(nB^2) \ B\)\(b\) 数组的值域

但是这种转移是类似前缀和的形式,所以可以利用一个前缀和数组 \(sum[j]\) 优化掉一维 \(B\)

这样空间上也可以优化至一维,\(dp\) 方程变得与 \(i\) 无关


Code

const int N = 3e3 + 5;
 
    int n, m, k, _;
    int a[N];
    int b[N];
    ll dp[N];
    ll sum[N];

ll adp(ll &x)
{
    x %= mod;
    x += mod;
    x %= mod;
    return x;
}

signed main()
{
    // IOS;
    while(~ sd(n)){
        rep(i, 1, n) sd(a[i]);
        rep(i, 1, n) sd(b[i]);
        for(int j = a[1]; j <= b[1]; j ++){
            dp[j] = 1;
            sum[j] = sum[j - 1] + dp[j];
        }
        for(int i = b[1] + 1; i <= b[2]; i ++){
            sum[i] = sum[i - 1];
        }
        for(int i = 2; i <= n; i ++){
            for(int j = a[i]; j <= b[i]; j ++){
                dp[j] = sum[j];
                adp(dp[j]);
            }
            sum[a[i] - 1] = 0;
            for(int j = a[i]; j <= b[i]; j ++){
                sum[j] = sum[j - 1] + dp[j];
                adp(sum[j]);
            }
            for(int j = b[i] + 1; j <= b[i + 1]; j ++){
                sum[j] = sum[j - 1];
            }
        }
        pll(sum[b[n]]);
    }
    // PAUSE;
    return 0;
}
posted @ 2021-11-03 09:00  Bcoi  阅读(142)  评论(0)    收藏  举报