AtCoder Beginner Contest 222 D - Between Two Arrays(前缀和优化dp)

简介: AtCoder Beginner Contest 222 D - Between Two Arrays(前缀和优化dp)

linkkkkk

题意:

给出两个长度为n的序列a , b构造一个序列c满足a i < = c i < = b i并且c非单调递减。求方案数。n < = 3000 , 0 < = a i , b i < = 3000

思路:

数据范围比较小,考虑d p

记d p [ i ] [ j ]表示选完了前i个数并且第i个数的值为j的方案数。

转移有d p [ i ] [ j ] = ∑ d p [ i − 1 ] [ k ] , a i − 1 < = k < = j

用前缀和优化一下,记s u m [ i ] [ j ]表示选了i个数并且第i个数的值< = j的方案数。

转移就变成了d p [ i ] [ j ] = s u m [ i − 1 ] [ j ] − s u m [ i − 1 ] [ a [ i − 1 ] − 1 ]

有几个小细节:

第i − 1层的s u m只维护到了b i − 1,所以如果j > b i − 1 的话,是没有值的,应该取m i n ( j , b i − 1 ) a i , b i都是可以为0 的话,如果为0的话,a [ i − 1 ] − 1就会变成− 1,但是不能跟0 取m a x,不然就会漏掉0的部分。我的处理方式是在输入的时候让所有的a , b都增加1,这样不会影响相对大小,下标也不是− 1

代码:

// Problem: D - Between Two Arrays
// Contest: AtCoder - Exawizards Programming Contest 2021(AtCoder Beginner Contest 222)
// URL: https://atcoder.jp/contests/abc222/tasks/abc222_d
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;typedef unsigned long long ull;
typedef pair<ll,ll>PLL;typedef pair<int,int>PII;typedef pair<double,double>PDD;
#define I_int ll
inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
#define read read()
#define rep(i, a, b) for(int i=(a);i<=(b);++i)
#define dep(i, a, b) for(int i=(a);i>=(b);--i)
ll ksm(ll a,ll b,ll p){ll res=1;while(b){if(b&1)res=res*a%p;a=a*a%p;b>>=1;}return res;}
const int maxn=4e5+7,maxm=1e6+7;
const ll mod=998244353;
ll dp[3100][3100],n,a[3100],b[3100];
ll sum[3100][3100];
int main(){
  n=read;
  rep(i,1,n) a[i]=read+1;
  rep(i,1,n) b[i]=read+1;
  for(int i=a[1];i<=b[1];i++) dp[1][i]=1,sum[1][i]=sum[1][i-1]+dp[1][i];
  for(int i=2;i<=n;i++)
    for(int j=a[i];j<=b[i];j++){
      if(j>=a[i-1])
        dp[i][j]=(dp[i][j]+sum[i-1][min(j*1ll,b[i-1])]-sum[i-1][max(0ll,a[i-1]-1)]+mod)%mod;
      sum[i][j]=(sum[i][j-1]+dp[i][j])%mod;
    }
  ll ans=0;
  for(int i=a[n];i<=b[n];i++)
    ans=(ans+dp[n][i])%mod;
  cout<<ans;
  return 0;
}



目录
相关文章
|
机器学习/深度学习
AtCoder Beginner Contest 215 F - Dist Max 2 (二分 单调队列)
AtCoder Beginner Contest 215 F - Dist Max 2 (二分 单调队列)
106 0
AtCoder Beginner Contest 203(Sponsored by Panasonic) D.Pond(二分+二维前缀和)
AtCoder Beginner Contest 203(Sponsored by Panasonic) D.Pond(二分+二维前缀和)
65 0
|
人工智能 BI
AtCoder Beginner Contest 216 F - Max Sum Counting (降维 背包dp)
AtCoder Beginner Contest 216 F - Max Sum Counting (降维 背包dp)
99 0
AtCoder Beginner Contest 214 F - Substrings(subsequence DP)
AtCoder Beginner Contest 214 F - Substrings(subsequence DP)
76 0
AtCoder Beginner Contest 226 E - Just one(dfs求连通块 组合数学)
AtCoder Beginner Contest 226 E - Just one(dfs求连通块 组合数学)
80 0
AtCoder Beginner Contest 214 D.Sum of Maximum Weights (思维 并查集)
AtCoder Beginner Contest 214 D.Sum of Maximum Weights (思维 并查集)
88 0
AtCoder Beginner Contest 225 F.String Cards(dp)
AtCoder Beginner Contest 225 F.String Cards(dp)
73 0
AtCoder Beginner Contest 216 G - 01Sequence (并查集 贪心 树状数组 差分约束)
AtCoder Beginner Contest 216 G - 01Sequence (并查集 贪心 树状数组 差分约束)
103 0
|
Java 程序员 开发者
LeetCode第三题(Longest Substring Without Repeating Characters)三部曲之一:解题思路
本文回顾了笔者对LeetCode第三题(Longest Substring Without Repeating Characters)的解题和优化思路,希望有兴趣的读者来一起广泛讨论
LeetCode第三题(Longest Substring Without Repeating Characters)三部曲之一:解题思路
AtCoder Beginner Contest 203 Pond(二分+二维前缀和)
大体思路: 二分,将原矩阵根据二分的值变成01矩阵,如果元素值> val 就变为1,否则0 对于k * k 的矩阵,统计区域内元素之和,如果 sum < ⌊k2 / 2⌋ + 1,意味着当前k * k矩阵的中位数小于x,而x是我们的答案(最小中位数), ①sum < ⌊k2 / 2⌋ + 1 情况下x取得太大,r = mid ②反之,x还可能取更小的,l = mid 但是需要注意下l的初始值,当取0 or 1的时候是会wa掉的:
208 0
AtCoder Beginner Contest 203 Pond(二分+二维前缀和)