CF 933A - A Twisty Movement(DP)

933A - A Twisty Movement

题意:给出一个只有 1 1 1 2 2 2组成的序列,有一次可以将区间 [ l , r ] [l,r] [l,r]逆置的机会,询问最长不下降子序列长度。

题解: d p [ i ] [ j ] [ k ] dp[i][j][k] dp[i][j][k]求出以 k k k结尾的区间 [ i , j ] [i,j] [i,j]的最长不上升子序列长度。然后答案就是 p r e [ i − 1 ] + m a x ( d p [ i ] [ j ] [ 1 ] , d p [ i ] [ j ] [ 2 ] ) + s u f [ j + 1 ] pre[i - 1] + max(dp[i][j][1],dp[i][j][2]) + suf[j + 1] pre[i1]+max(dp[i][j][1],dp[i][j][2])+suf[j+1],这里 p r e pre pre代表前 i i i个数中 1 1 1的个数, s u f suf suf代表后 j j j个数中 2 2 2的个数。

代码

#include
using namespace std;
#ifndef ONLINE_JUDGE
#define dbg(args...)                                   \
    do{                                                \
	        cout << "\033[32;1m" << #args << " -> ";   \
         err(args);                                    \
      } while(0)                                       
#else
#define dbg(...)
#endif
void err()
{
    cout << "\033[39;0m" << endl;
}
template <template <typename...> class T, typename t, typename... Args>
void err(T<t> a, Args... args)
{
    for (auto x : a) cout << x << ' ';
    err(args...);
}
template <typename T, typename... Args>
void err(T a, Args... args)
{
    cout << a << ' ';
    err(args...);
}
/****************************************************************************************************/
constexpr int N = 2056;
int dp[N][N][3], sum[N][3], a[N];

int main() {
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
    ios::sync_with_stdio(false); cin.tie(0);
	int n;
	cin >> n;
	for(int i = 1; i <= n; ++i) {
		cin >> a[i];
		sum[i][1] = sum[i - 1][1]; 
		sum[i][2] = sum[i - 1][2];
		sum[i][a[i]]++;
	}
	for(int i = 1; i <= n; ++i) {
		for(int w = 1; w + i - 1 <= n; ++w) {
			int j = i + w - 1;
	//		dbg(j);
			dp[i][j][1] = dp[i][j - 1][1];
			dp[i][j][2] = dp[i][j - 1][2];
			if(a[j] == 1) {
				dp[i][j][1] = max(dp[i][j - 1][1], dp[i][j - 1][2]) + 1;
			} 
			if(a[j] == 2) {
				dp[i][j][2] = dp[i][j - 1][2] + 1;
			}
		}
	}
	int ans = 0;
	for(int i = 1; i <= n; ++i) {
		for(int w = 1; w + i - 1 <= n; ++w) {
			int j = i + w - 1, t = sum[n][2] - sum[j][2];
	//		dbg(sum[i - 1][1],dp[i][j][1],dp[i][j][2],t);
			ans = max(ans, sum[i - 1][1] + max(dp[i][j][1], dp[i][j][2]) + t);
		}
	}
	cout << ans << '\n';
    return 0;
}

你可能感兴趣的:(CodeForces,ACM,动态规划)