专栏文章

题解:CF1067A Array Without Local Maximums

CF1067A题解参与者 9已保存评论 8

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
8 条
当前快照
1 份
快照标识符
@mio0ex1t
此快照首次捕获于
2025/12/02 11:19
3 个月前
此快照最后确认于
2025/12/02 11:19
3 个月前
查看原文
这题很显然吧。设 m=200m=200,对大小 [1,m][1,m] 下手即可。然后转移状态时考虑大小为 xx 的可行性,若 aia_i 确定强制转移即可。
这个时候我们发现转移过程有点冗余了,每次暴力 ai1a_{i-1} 的大小转移,需要 O(nm2)O(nm^2),不妨考虑加一维表示相对大小,然后通过前缀和来优化掉冗余的转移。那么优化到 O(nm)O(nm) 可过。
具体来讲,设 fi,j,0/1/2f_{i,j,0/1/2} 表示第 ii 位大小为 jj 的方案数,而 0/1/20/1/2 分别表示 ai1<aia_{i-1}<a_iai1=aia_{i-1}=a_iai1>aia_{i-1}>a_i
  • 对于状态 00,显然 ai1a_{i-1}ai2a_{i-2} 大小关系如何都无所谓,因为 aia_i 帮助 ai1a_{i-1} 完成了限制条件,故 fi,j,0=k=1j1fi1,k,0+fi1,k,1+fi1,k,2f_{i,j,0}=\sum\limits^{j-1}_{k=1}f_{i-1,k,0}+f_{i-1,k,1}+f_{i-1,k,2}
  • 对于状态 11,与状态 00 一样不用考虑前者的相对大小,fi,j,1=fi1,j,0+fi1,j,1+fi1,j,2f_{i,j,1}=f_{i-1,j,0}+f_{i-1,j,1}+f_{i-1,j,2}
  • 对于状态 22,显然只能从 1,21,2 转移过来,不然 ai1a_{i-1} 就无法满足限制条件了,故 fi,j,2=k=j+1mfi1,k,1+fi1,k,2f_{i,j,2}=\sum\limits^m_{k=j+1}f_{i-1,k,1}+f_{i-1,k,2}
这个时候不难发现,对 fi1,k,0+fi1,k,1+fi1,k,2f_{i-1,k,0}+f_{i-1,k,1}+f_{i-1,k,2} 做一个前缀和,对 fi1,k,1+fi1,k,2f_{i-1,k,1}+f_{i-1,k,2} 做一个后缀和,就可以 O(m)O(m) 转移一次状态。
总体时间复杂度 O(nm)O(nm)
评测记录 #336937092
CPP
#include <bits/stdc++.h>
#define int long long
#define lint long long
#define endl '\n'
using namespace std;
const int N = 1e5+5;
const int M = 2e2+5;
const int mod = 998244353;
 
int n,m,a[N];
int pre[M],suf[M];
int f[N][M][3];
 
inline void init(int i){
	for(int j = 1; j <= m; j++){
		pre[j] = pre[j-1] + f[i-1][j][0] + f[i-1][j][1] + f[i-1][j][2];
		pre[j] %= mod;
	}
 
	for(int j = m; j >= 1; j--){
		suf[j] = suf[j+1] + f[i-1][j][1] + f[i-1][j][2];
		suf[j] %= mod;
	}
}
 
inline void check(int i,int l,int r){
	init(i);
	
	for(int j = l; j <= r; j++){
		f[i][j][0] = pre[j-1],f[i][j][2] = suf[j+1];
		f[i][j][1] = f[i-1][j][0] + f[i-1][j][1] + f[i-1][j][2];
		f[i][j][1] %= mod;
	}
}
 
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
 
	// freopen("app.in","r",stdin);
    // freopen("app.out","w",stdout);
	
	m = 200;
 
	cin >> n;
	for(int i = 1; i <= n; i++)
		cin >> a[i];
 
	if(a[1] == -1)
		for(int j = 1; j <= m; j++)
			f[1][j][0] = 1;
	else f[1][a[1]][0] = 1;
 
	for(int i = 2; i <= n; i++){
		if(a[i] == -1) check(i,1,m);
		else check(i,a[i],a[i]);
	}
 
	int ans = 0;
	if(a[n] == -1){
		for(int j = 1; j <= m; j++){
			ans += f[n][j][1] + f[n][j][2];
			ans %= mod;
		}
	}else ans = (f[n][a[n]][1] + f[n][a[n]][2]) % mod;
 
	cout << ans << endl;
	return 0;
} 

评论

8 条评论,欢迎与作者交流。

正在加载评论...