题解:AT_arc127_e [ARC127E] Priority Queue
题解
每个权值的最终状态只有删与不删,我们只需要统计有多少最终状态是合法的。
将操作序列从左往右排开为 \(A\) 个点 \(B\) 条竖线的序列:

点被竖线分成了若干段,同一段内交换顺序不影响最终状态,于是不妨把红点放在每一段的最后一个。这样上面每个位置的颜色都是确定的。

- 一个球的序列合法当且仅当,对于每个红球,它比前面的黄球都大。
- 一种对 \(1 \sim n\) 球的染色方案合法,当且仅当任意安排同色球的顺序,存在一个球的序列合法。
所以我们要 Check 一种染色方案,只需要它的最优的球的序列合法就行了,最优的显然是排序后的。
- 贪心地,将两种颜色的球分别排序:\(Y_1 \leq Y_2 \leq \cdots Y_{A-B}\),\(R_1 \leq R_2 \leq \cdots \leq R_{B}\)(限制一)。
- 对于每个红球,它比前面的黄球都大(限制二)。
- 权值 \(1 \sim A\) 恰好出现一次(限制三)。
每种合法的染色方案和满足上述限制的序列一一对应,所以最终转化为统计以上序列的数量。
DP 非常好做,设 \(f_{i,j}\) 表示考虑了 \(i \sim n\) 的权值,已经染了 \(R_j \sim R_B\) 的红球。
考虑 \(i-1\) 删不删(省略了转移条件):
- 权值 \(i-1\) 染红,成为红球 \(R_{j-1}\):\(f_{i-1,j-1} \leftarrow f_{i,j}\)。
- 权值 \(i-1\) 染黄:\(f_{i-1,j} \leftarrow f_{i,j}\)。
最终答案为 \(f_{1,1}\)。
代码
#include<bits/stdc++.h>
#define For(i,il,ir) for(int i=(il);i<=(ir);++i)
#define Rof(i,ir,il) for(int i=(ir);i>=(il);--i)
using namespace std;
typedef long long ll;
void qadd(ll &x,ll y){ x=(x+y>=998244353)?(x+y-998244353):(x+y); }
const int N=5005;
ll f[N][N];
int m,A,B;
int q[N],pos[N],t,n,x;
signed main()
{
scanf("%d%d",&A,&B);
For(i,1,A+B){
scanf("%d",&x);
if(x==1) q[++t]=++n;
else pos[++m]=q[t--];
}
sort(pos+1,pos+1+m);
f[A+1][m+1]=1ll;
Rof(i,A+1,2)
Rof(j,m+1,1){
if(j>1) qadd(f[i-1][j-1],f[i][j]);
if(i-1>pos[j-1]) qadd(f[i-1][j],f[i][j]);
}
printf("%lld\n",f[1][1]);
return 0;
}

浙公网安备 33010602011771号