题解: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}\)

代码

Atcoder 提交记录

#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;
}
posted @ 2025-04-09 13:03  wanggk  阅读(16)  评论(0)    收藏  举报