zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    浅谈 js字符串 trim 方法之正则篇
    各大型网站使用的服务器空间运行环境盘点
    博客打开慢?请禁用WordPress默认的谷歌字体!
    巧妙设计:让页面活起来
    最流行的JavaScript库jQuery不再支持旧版IE
    Spring各个版本源码下载地址
    mysql 修改字符集
    Spring AOP aspectjweaver.jar与aopalliance-1.0.jar 下载地址
    <<Java | Java正则表达式 | 学习总结>>
    <Java并发编程实战 | 前言 | 学习总结>
  • 原文地址:https://www.cnblogs.com/BIGTOM/p/8449540.html
Copyright © 2011-2022 走看看