Codeforces 934.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组成的序列,要求翻转一个区间,使得最长不下降子序列尽可能长.

分析:读错题坑了我40分钟.子序列可以不连续!

   考虑没有翻转操作.那么答案肯定是一个位置左边的1的数量+右边的2的数量,取max. 那么我们可以统计1的前缀和,2的后缀和.

   如果有翻转操作.其实就是翻转的区间中的一个位置统计1的后缀和,同时在这个位置统计2的前缀和,最后和两个端点处的相减.

具体来说,如果记sum1为1的前缀和,sum2为2的后缀和,sum3为1的后缀和,sum4为2的前缀和,翻转的两个区间端点为a,b.那么答案就是max{sum1[a - 1] + sum2[b + 1] + sum3[i + 1] - sum3[b + 1] + sum4[i] - sum4[a - 1]}.实际上变动的就是sum3[i + 1]与sum4[i],求出一个区间内它们的最大值,有很多方法.我偷懒用线段树维护.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;

int n,a[2010],ans,f[2010][2010],sum1[2010],sum2[2010],sum3[2010],sum4[2010],b[2010],maxx[2010 << 2];

void pushup(int o)
{
    maxx[o] = max(maxx[o * 2],maxx[o * 2 + 1]);
}

void build(int o,int l,int r)
{
    if (l == r)
    {
        maxx[o] = b[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(o * 2,l,mid);
    build(o * 2 + 1,mid + 1,r);
    pushup(o);
}

int query(int o,int l,int r,int x,int y)
{
    if (x <= l && r <= y)
        return maxx[o];
    int mid = (l + r) >> 1,res = -100000000;
    if (x <= mid)
        res = max(res,query(o * 2,l,mid,x,y));
    if (y > mid)
        res = max(res,query(o * 2 + 1,mid + 1,r,x,y));
    return res;
}

int main()
{
    scanf("%d",&n);
    for (int i = 1; i <= n; i++)
        scanf("%d",&a[i]);
    for (int i = 1; i <= n; i++)
        sum1[i] = sum1[i - 1] + (a[i] == 1 ? 1 : 0);
    for (int i = n; i >= 1; i--)
        sum2[i] = sum2[i + 1] + (a[i] == 2 ? 1 : 0);
    for (int i = n; i >= 1; i--)
        sum3[i] = sum3[i + 1] + (a[i] == 1 ? 1 : 0);
    for (int i = 1; i <= n; i++)
        sum4[i] = sum4[i - 1] + (a[i] == 2 ? 1 : 0);
    for (int i = 0; i <= n; i++)
        b[i] = sum4[i] + sum3[i + 1];
    build(1,0,n);
    for (int i = 1; i <= n; i++)
    {
        for (int j = i; j <= n; j++)
        {
            int temp = query(1,0,n,i - 1,j);
            ans = max(ans,sum1[i - 1] + sum2[j + 1] + temp - sum3[j + 1] - sum4[i - 1]);
        }
    }
    printf("%d\n",ans);

    return 0;
}

 

 

posted @ 2018-02-15 10:14  zbtrs  阅读(507)  评论(0编辑  收藏  举报