考虑特值
n为奇无解
n为偶数, a , b , c = [ 0 , 0 , n / 2 ] a,b,c = [0,0,n/2] a , b , c = [ 0 , 0 , n / 2 ] ;
Code
1 2 3 4 5 6 7 8 void solve () { int n; cin>>n; if (n&1 ) cout << -1 << endl; else { cout << 0 <<" " << 0 <<" " << n/2 << endl; } }
观察可知
r e s res r e s 的子矩阵为:
1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 1 \begin{matrix}
1&0&0&1\\
0&1&1&0\\
0&1&1&0\\
1&0&0&1
\end{matrix}
1 0 0 1 0 1 1 0 0 1 1 0 1 0 0 1
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int n,m;string s[51 ]; void init () { forr(i,0 ,49 ){ int f = 0 ; forr(j,1 ,25 ){ if (i%4 ==0 || i%4 ==3 ){ if (!f) s[i] += "10" ; else s[i] += "01" ; f ^= 1 ; } else { if (!f) s[i] += "01" ; else s[i] += "10" ; f ^= 1 ; } } } } void solve () { cin>>n>>m; forr(i,1 ,n){ forr(j,1 ,m){ if (s[i-1 ][j-1 ] == '0' ) cout << 0 <<" " ; else cout << 1 <<" " ; } cout << endl; } }
对于区间 [ l , r ] [l,r] [ l , r ] M E X ( [ a l , , , a r ] ) = x MEX([a_l,,,a_r]) = x M E X ( [ a l , , , a r ] ) = x 说明 [ 0 , x − 1 ] [0,x-1] [ 0 , x − 1 ] 均在区间[ l , r ] [l,r] [ l , r ] 内
所以枚举 i i i ∈ [0,n-1],并维护 [ 0 , i − 1 ] [0,i-1] [ 0 , i − 1 ] 能到达的最左和最右端点(L,R)
枚举 i i i 的位置 p [ i ] p[i] p [ i ] ,若 p [ i ] p[i] p [ i ] 在 ( L , R ) (L,R) ( L , R ) 内,那么 i i i 可以放在剩下的位置 ( l e n − i ) (len - i) ( l e n − i )
l e n = R − L + 1 len = R - L + 1 l e n = R − L + 1 ,区间 [ L , R ] [L,R] [ L , R ] 已经放了[ 0 , i − 1 ] [0,i-1] [ 0 , i − 1 ] i个数,
对 r e s res r e s 的贡献为 r e s ∗ = ( R − L + 1 − i ) res \ *= (R-L+1-i) r e s ∗ = ( R − L + 1 − i )
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void solve () { int n;cin>>n; vector<int > a (n+1 ) ,p (n+1 ) ; forr(i,1 ,n) cin >> a[i],p[a[i]] = i; int l = inf,r = -inf; int res = 1 ; forr(i,0 ,n-1 ){ if (l <= p[i] && p[i] <= r){ res *= (r-l+1 -i); res %= mod; } l = min (l,p[i]); r = max (r,p[i]); } cout << res << endl; }
一段连续的数可以完全删完需要满足
长度为偶数
众数个数不大于长度一半
根据 n < = 5000 n <= 5000 n < = 5 0 0 0 ,可以 n 2 n^2 n 2 的处理出所有区间能否转移的情况
考虑 dp[i] 表示以第i位结尾并且作为答案贡献的最大个数
转移方程
d p [ i ] = m a x ( d p [ i ] , d p [ j ] + 1 ) a [ i ] = = a [ j ] & & o k ( i + 1 , j − 1 ) dp[i] = max(dp[i],dp[j]+1) \ a[i] == a[j] \&\& ok(i+1,j-1) d p [ i ] = m a x ( d p [ i ] , d p [ j ] + 1 ) a [ i ] = = a [ j ] & & o k ( i + 1 , j − 1 )
要预处理 d p dp d p 当 o k ( 1 , i − 1 ) d p [ i ] = 1 ok(1,i-1) \ dp[i] = 1 o k ( 1 , i − 1 ) d p [ i ] = 1 表示 i i i 以前的数可以完全删除
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 int f[5005 ][5005 ];bool ok (int l,int r) { if (r-l+1 <= 0 ) return 1 ; return (r-l+1 )%2 ==0 && f[l][r]; } void solve () { int n;cin>>n; vector<int > a (n+1 ) ; forr(i,1 ,n) cin >> a[i]; forr(i,1 ,n){ vector<int > cot (n+1 ,0 ) ; int mx = -inf; forr(j,i,n){ ++cot[a[j]]; mx = max (mx,cot[a[j]]); f[i][j] = (2 *mx<=(j-i+1 )); } } vector<int > dp (n+5 ,-inf) ; forr(i,1 ,n) if (ok (1 ,i-1 )) dp[i] = 1 ; forr(i,1 ,n){ for (int j = i-1 ;j>=1 ;j--){ if (ok (j+1 ,i-1 ) && a[i] == a[j]) dp[i] = max (dp[i],dp[j]+1 ); } } int res = 0 ; forr(i,1 ,n) if (ok (i+1 ,n)) res = max (res,dp[i]); cout << res << '\n' ; }