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