ABC222 D - Between Two Arrays(dp)
阿新 • • 發佈:2021-11-03
目錄
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; }