Codeforces Round #462 (Div. 2) C. A Twisty Movement

C. A Twisty Movement
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

A dragon symbolizes wisdom, power and wealth. On Lunar New Year's Day, people model a dragon with bamboo strips and clothes, raise them with rods, and hold the rods high and low to resemble a flying dragon.

A performer holding the rod low is represented by a 1, while one holding it high is represented by a 2. Thus, the line of performers can be represented by a sequence a1, a2, ..., an.

Little Tommy is among them. He would like to choose an interval [l, r] (1 ≤ l ≤ r ≤ n), then reverse al, al + 1, ..., ar so that the length of the longest non-decreasing subsequence of the new sequence is maximum.

A non-decreasing subsequence is a sequence of indices p1, p2, ..., pk, such that p1 < p2 < ... < pk and ap1 ≤ ap2 ≤ ... ≤ apk. The length of the subsequence is k.

Input

The first line contains an integer n (1 ≤ n ≤ 2000), denoting the length of the original sequence.

The second line contains n space-separated integers, describing the original sequence a1, a2, ..., an (1 ≤ ai ≤ 2, i = 1, 2, ..., n).

Output

Print a single integer, which means the maximum possible length of the longest non-decreasing subsequence of the new sequence.

Examples
input
4
1 2 1 2
output
4
input
10
1 1 2 2 2 1 1 2 2 1
output
9
Note

In the first example, after reversing [2, 3], the array will become [1, 1, 2, 2], where the length of the longest non-decreasing subsequence is 4.

In the second example, after reversing [3, 7], the array will become [1, 1, 1, 1, 2, 2, 2, 2, 2, 1], where the length of the longest non-decreasing subsequence is 9.

思路一:(比赛时的想法)先对于原始序列,预处理出每个位置(含本身)之前有多少个1,之后有多少个2,然后再扫一遍统计出没翻转时的最大答案。之后考虑翻转后的情况,对于每个合法子序列,把第一次出现2的位置定义为分隔点,那么如果分隔点在翻转区间外,对结果是没有影响的,要考虑的只是分隔点在翻转区间内部的情况。暴力枚举区间并统计是O(n^3)的,考虑一下优化。枚举区间时,固定左端点,右端点向右移动,每次新出现的元素如果是1,那么统计值直接加1,如果是2,要想对答案有影响,那么这段翻转区间的贡献就是2的个数,这个东西可以用个常量维护出来。时间复杂度O(n*n),空间复杂度O(n)。

废话:从看题到过题用了20分钟,当时感觉自己分析的很精髓,此时大概40到50人过了这题,rank17,内心小得意。刚才才知道可以O(n)做,看来分析地并不精髓,果然还是菜...

#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <iomanip>
#include <cctype>
#include <cassert>
#include <bitset>
#include <ctime>

using namespace std;

#define pau system("pause")
#define ll long long
#define pii pair<int, int>
#define pb push_back
#define mp make_pair
#define clr(a, x) memset(a, x, sizeof(a))

const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double EPS = 1e-9;

int n, a[2015];
int pre1[2015], suf2[2015], ans;
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    for (int i = 1; i <= n; ++i) {
        pre1[i] = (1 == a[i] ? pre1[i - 1] + 1 : pre1[i - 1]);
    }
    for (int i = n; i; --i) {
        suf2[i] = (2 == a[i] ? suf2[i + 1] + 1 : suf2[i + 1]);
    }
    for (int i = 1; i <= n; ++i) {
        if (2 == a[i]) {
            ans = max(ans, pre1[i] + suf2[i]);
        }
    }
    for (int l = 1; l <= n; ++l) {
        int t1 = pre1[l - 1], ma = 0, cnt_2 = 0;
        for (int r = l; r <= n; ++r) {
            int t2 = suf2[r + 1];
            if (1 == a[r]) {
                ++ma;
            } else {
                ++cnt_2;
                ma = max(ma, cnt_2);
            }
            ans = max(ans, t1 + t2 + ma);
        }
    }
    printf("%d
", ans);
    return 0;
}

思路二:翻转后的合法子序列翻转前一定是 一坨1 + 一坨2 + 一坨1 + 一坨2形式,坨可以为空,于是可以用4个变量分别维护前1坨,前2坨,前3坨,前4坨的最大值,更新时每个变量也只用上一轮最多两个变量更新,比如当前元素为2,那么前两坨的最大值ma2 = max(ma1, ma2) + 1,ma4 = max(ma3, ma4) + 1。因为将2接到ma1或ma2后的序列都是合法的ma2形式。代码十分简短。时间复杂度O(n),空间复杂度O(1)。

#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <map>
#include <list>
#include <iomanip>
#include <cctype>
#include <cassert>
#include <bitset>
#include <ctime>

using namespace std;

#define pau system("pause")
#define ll long long
#define pii pair<int, int>
#define pb push_back
#define mp make_pair
#define clr(a, x) memset(a, x, sizeof(a))

const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const double EPS = 1e-9;

int ma1, ma2, ma3, ma4, x, n;
int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &x);
        if (1 == x) {
            ++ma1;
            ma3 = max(ma3, ma2) + 1;
        } else {
            ma2 = max(ma1, ma2) + 1;
            ma4 = max(ma4, ma3) + 1;
        }
    }
    printf("%d
", max(ma3, ma4));
    return 0;
}
原文地址:https://www.cnblogs.com/BIGTOM/p/8449540.html