ACM----CodeForces Round #700 (Div. 1)B1. Painting the Array I

B1. Painting the Array I
time limit per test
2 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

The only difference between the two versions is that this version asks the maximal possible answer.

Homer likes arrays a lot. Today he is painting an array a1,a2,,ana1,a2,…,an with two kinds of colors, white and black. A painting assignment for a1,a2,,ana1,a2,…,an is described by an array b1,b2,,bnb1,b2,…,bn that bibi indicates the color of aiai (00 for white and 11 for black).

According to a painting assignment b1,b2,,bnb1,b2,…,bn, the array aa is split into two new arrays a(0)a(0) and a(1)a(1), where a(0)a(0) is the sub-sequence of all white elements in aa and a(1)a(1) is the sub-sequence of all black elements in aa. For example, if a=[1,2,3,4,5,6]a=[1,2,3,4,5,6] and b=[0,1,0,1,0,0]b=[0,1,0,1,0,0], then a(0)=[1,3,5,6]a(0)=[1,3,5,6] and a(1)=[2,4]a(1)=[2,4].

The number of segments in an array c1,c2,,ckc1,c2,…,ck, denoted seg(c)seg(c), is the number of elements if we merge all adjacent elements with the same value in cc. For example, the number of segments in [1,1,2,2,3,3,3,2][1,1,2,2,3,3,3,2] is 44, because the array will become [1,2,3,2][1,2,3,2] after merging adjacent elements with the same value. Especially, the number of segments in an empty array is 00.

Homer wants to find a painting assignment bb, according to which the number of segments in both a(0)a(0) and a(1)a(1), i.e. seg(a(0))+seg(a(1))seg(a(0))+seg(a(1)), is as large as possible. Find this number.

Input

The first line contains an integer nn (1n1051≤n≤105).

The second line contains nn integers a1,a2,,ana1,a2,…,an (1ain1≤ai≤n).

Output

Output a single integer, indicating the maximal possible total number of segments.

Examples
input
7
1 1 2 2 3 3 3
output
6
input
7
1 2 3 4 5 6 7
output
7
Note

In the first example, we can choose a(0)=[1,2,3,3], a(1)=[1,2,3] and seg(a(0))=seg(a(1))=3seg(a(0))=seg(a(1))=3. So the answer is 3+3=63+3=6.

In the second example, we can choose a(0)=[1,2,3,4,5,6,7] and a(1) is empty. We can see that seg(a(0))=7seg(a(0))=7 and seg(a(1))=0seg(a(1))=0. So the answer is 7+0=77+0=7.

题目大意:将给定的一段序列分成两部分,分别将每部分相邻的相同元素合并,最后使两部分的元素个数和最大。

解题思路:由于是要求最大值,首先考虑贪心,按步骤讨论最优解。设分成的两部分为a0和a1,因为是要将a0和a1的相邻的相同元素合并,所以在决定将待插元素放到哪个部分时要考虑当前两部分的最后一个元素。

设当前待分的元素为a[i],待分元素的下一个元素为a[i+1],a0序列的最后一个元素为ae0,a1的最后一个元素为ae1。设计数器count记录合并后两个序列的元素个数和:

  当a[i]==ae0&&a[i]==ae1时,无论分到那部分对个数总和和两部分的最后一个元素都没有影响,直接进行下一个元素的分配。

  当a[i]==ae0时,应该将a[i]分给a1部分,计数器count++,ae1=a[i];

  当a[i]==ae1时,应该将a[i]分给a0部分,计数器count++,ae0=a[i];

  当a[i]!=ae0&&a[i]!=ae1时,首先将计数器自增,随后通过考虑当前待分元素的下一个元素a[i+1]与当前ae0和ae1的关系来决定将a[i]放到哪个部分:

    当a[i+1]==ae0&&a[i+1]!=ae1时,应该将a[i]分给a0部分用当前元素将两个相同的元素a[i+1]与ae0分开以达到最优解

    当a[i+1]==ae1&&a[i+1]!=ae0时,应该将a[i]分给a1部分

代码实现:

#include<cstdio>
int main(){
    int n;
    int a[1000000];
    scanf("%d",&n);

    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
    int ae0=-1,ae1=-1;
    int count=0;

    for(int i=0;i<n;i++){
        if(a[i]==ae0&&a[i]==ae1) continue;
        else if(a[i]==ae0){
            ae1=a[i];
            count++;
        }
        else if(a[i]==ae1){
            ae0=a[i];
            count++;
        }
        else{
            count++;
            if(a[i+1]==ae0&&a[i+1]!=ae1) ae0=a[i];
            else if(a[i+1]!=ae0&&a[i+1]==ae1) ae1=a[i];
            else ae0=a[i];
        }
    }
    printf("%d\n",count);
    return 0;
}

 

posted @ 2021-02-10 16:32  AA、  阅读(138)  评论(0编辑  收藏  举报