题解 ARC171B【Chmax】

考察题面中的操作究竟做了什么,不难发现其实是将所有满足 \(P_i > i\)\(i\to P_i\) 连边,得到若干条链,然后 \(B_i\) 即为 \(i\) 所在链的最后一个节点。

显然,存在 \(A_i < i\) 时无解,存在 \(A_i\ne i\)\(A_j = i\) 时也无解。

否则,每个 \(A_i\ne i\) 的位置填的数都唯一确定了(必须是下一个满足 \(A_j=A_i\)\(j\)),只需计算将剩下的数填入 \(P\) 中,且满足 \(P_i < i\) 的方案数。这个是十分容易的。具体来说就是从小到大枚举 \(i\),统计有多少个不超过 \(i\) 的数还没有用过,然后如果当前位置需要填一个数,就从这些数中选择一个填入,乘法原理统计即可。

typedef Modint<998244353> mint;

int n, a[N], lst[N], vis[N];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cin >> n;
    rep(i, 1, n) cin >> a[i];
    per(i, n, 1) {
    	if(a[i] < i) {
    		cout << 0 << endl;
    		return 0;
    	}
    	if(lst[a[i]]) vis[lst[a[i]]] = 1;
    	else if(i != a[i]) {
    		cout << 0 << endl;
    		return 0;
    	}
    	lst[a[i]] = i;
    }
    mint cnt = 0, ans = 1;
    rep(i, 1, n) {
	    cnt += !vis[i];
    	if(i == a[i]) {
	    	ans *= cnt;
	    	--cnt;
	    }
    }
    cout << ans << endl;
    return 0;
}
posted @ 2024-02-05 16:07  rui_er  阅读(59)  评论(0编辑  收藏  举报