Problem - D1 - Codeforces (Unofficial mirror by Menci)
D1. Range Sorting (Easy Version) - 区间DP解法
贪心结论:
- 操作的区间都不相交
用反证法证明,如果存在两个相交的区间,那么把相交的区间,合并成一个,结果一定更优.
设dp[l][r] 表示 区间(l,r)需要的最少操作次数
- 当a[l] > a[r] 时,操作区间(l,r)必然是最优的
- 将(l,r-1)与(l+1,r)的操作区间都合并起来,结果肯定是最优的.
那么如何得到合并之后的操作长度?
可以通过容斥: Dp[l][r-1] + dp[l+1][r] - dp[l+1][r-1] 即可得到合并后的操作区间长度.
#include <bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
#define int long long
#define endl '\n'
#define bit(x) (1ll << x)
using namespace std;
const int N = 1e6 + 5;
const int inf = 1e16;
void solve()
{
int n;
cin >> n;
vector<int> a(n + 1);
vector<vector<int>> dp(n + 1, vector<int>(n + 1));
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
int ans = 0;
for(int len = 2; len<=n; len++)
{
for(int l = 1; l+len-1<=n; l++)
{
int r = l+len-1;
if(a[l] > a[r])
{
dp[l][r] = r-l;
}
else
{
dp[l][r] = dp[l+1][r] + dp[l][r-1] - dp[l+1][r-1];
}
ans+=dp[l][r];
}
}
cout << ans << endl;
}
signed main()
{
ios_base::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int t = 1;
cin >> t;
while (t--)
{
solve();
}
return 0;
}