ARC127E Priority Queue
ARC127E Priority Queue
分析性质+dp。
思路
由于每次加入的数肯定是一个 \(a\) 的排列,但这个角度不好考虑。
设 \(\{a\}\) 为最终状态的集合,其中 \(a_i<a_{i+1}\),显然集合内元素个数为 \(A-B\)。
然后可以发现,按照元素值升序的加入顺序形成最终状态一定是最保险的一种方案。
设 \(a_{i+1},a_i\) 加入的顺序可以形成该最终状态,试交换顺序为 \(a_i,a_{i+1}\)。
-
因为 \(a_i<a_{i+1}\) 所以 \(a_i\) 可以留下。
-
因为 \(a_{i+1},a_i\) 的顺序可以形成最终状态,所以 \(a_i,a_{i+1}\) 也可以形成最终状态。
所以如果乱序加入的状态可以留下 \(a_i,a_{i+1}\),那么升序加入一定可以留下。
那么我们可以发现,最后留下的顺序是升序的,就可以考虑 \(dp\)。
设 \(dp[i][j]\) 为目前已经放了 \(i-1\) 个数,第 \(i\) 个数放 \(j\) 的状态数。
有转移:
\[dp[i][j]=\sum_{k=1}^{j-1} dp[i-1][k]
\]
可以用前缀和优化转移,时间复杂度 \(O(n^2)\)。
CODE
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 998244353
const int maxn=5005;
int n,a,b,t,m;
int r[maxn];
ll dp[maxn][maxn],s[maxn][maxn];
int main()
{
scanf("%d%d",&a,&b);
for(int i=1;i<=a+b;i++)
{
int x;
scanf("%d",&x);
if(x==1) r[++t]=++m;
else t--;
}
dp[0][0]=1;
for(int i=0;i<=a;i++) s[0][i]=1;
for(int i=1;i<=a-b;i++)
{
for(int j=1;j<=r[i];j++)
dp[i][j]=s[i-1][j-1],s[i][j]=(dp[i][j]+s[i][j-1])%mod;
for(int j=r[i]+1;j<=a;j++) s[i][j]=s[i][r[i]];
}
printf("%lld",s[a-b][r[a-b]]);
}

浙公网安备 33010602011771号