题解:CF1987F2 Interesting Problem (Hard Version)
KingPowers · · 题解
场上瞪了一个小时一点不会,狠狠意识到我对区间 dp 一无所知。
考虑如果我们希望
-
-
- 需要在
[1,i-1] 这段前缀中恰好删去\frac{i-a_i}{2} 个数使得a_i=i 。
结合第三条与数据范围,可以想到一个区间 dp:设
还有一种特殊的转移,我们可以将
随后考虑如何求答案,令
时间复杂度
#include<bits/stdc++.h>
#define For(i, a, b) for(int i = (a); i <= (b); i++)
#define Rof(i, a, b) for(int i = (a); i >= (b); i--)
using namespace std;
const int N = 805, INF = 1e9;
int n, a[N], f[N][N], g[N];
void Solve(){
cin >> n;
For(i, 1, n) cin >> a[i];
For(l, 1, n) For(r, 1, n) f[l][r] = INF;
for(int len = 2; len <= n; len += 2)
For(l, 1, n - len + 1){
int r = l + len - 1, v = (l - a[l]) / 2;
if((l % 2 != a[l] % 2) || l < a[l]) continue;
if(len == 2 || f[l + 1][r - 1] * 2 <= (l - a[l])) f[l][r] = v;
for(int k = l + 1; k <= r - 1; k += 2){
int nv = max({v, f[l][k], f[k + 1][r] - (k - l + 1) / 2});
f[l][r] = min(f[l][r], nv);
}
}
For(i, 1, n){
g[i] = g[i - 1];
for(int len = 1; 2 * len <= i; len++)
if(f[i - 2 * len + 1][i] <= g[i - 2 * len]) g[i] = max(g[i], g[i - 2 * len] + len);
}
cout << g[n] << '\n';
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int T = 1; cin >> T;
while(T--) Solve();
return 0;
}