1480D1.Painting the Array I(分类讨论)

这两个版本之间的唯一区别是,此版本要求的是最大可能的答案。

荷马非常喜欢数组。今天,他正在绘制一个数组a1,a2,…,an,它具有白色和黑色两种颜色。 a1,a2,…,an的绘画分配由数组b1,b2,…,bn描述,bi指示ai的颜色(白色为0,黑色为1)。

根据绘画任务b1,b2,…,bn,将数组a拆分为两个新数组a(0)和a(1),其中a(0)是a和a中所有白色元素的子序列(1)是a中所有黑色元素的子序列。例如,如果a = [1,2,3,4,5,6]并且b = [0,1,0,1,0,0],则a(0)= [1,3,5,6 ]和a(1)= [2,4]。

如果我们将c中具有相同值的所有相邻元素合并,则数组s1,c2,…,ck中表示为seg(c)的段数就是元素数。例如,[1,1,2,2,3,3,3,2]中的段数为4,因为合并具有相同值的相邻元素后数组将变为[1,2,3,2] 。特别是,空数组中的段数为0。

荷马想找到一个绘画作业b,根据该作业,a(0)和a(1)中的段数尽可能大,即seg(a(0))+ seg(a(1)) 。找到这个号码。

输入值
第一行包含一个整数n(1≤n≤105)。

第二行包含n个整数a1,a2,…,an(1≤ai≤n)。

输出量
输出单个整数,指示最大可能的段总数。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;
int n,a[maxn];
int is[maxn];
vector<pair<int,int> > p1,p2;
int main () {
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",a+i);
    int ans=0;
    int tot=0;
    for (int i=1;i<=n;i++) {
        int j;
        for (j=i;j<=n;j++) if (a[j]!=a[i]) break;
        if (j-i>1) {
            p2.push_back(make_pair(a[i],i));
        } 
        p1.push_back(make_pair(a[i],i));
        if (j-i==1) is[i]=1;
        i=j-1; 
    }
    for (int i=0;i<p1.size();i++) {
        int j;
        for (j=i;j<p1.size();j++) if (p1[j].first!=p1[i].first) break;
        ans++;
        i=j-1;
    }
    for (int i=0;i<p2.size();i++) {
        int j;
        for (j=i;j<p2.size();j++) if (p2[j].first!=p2[i].first) break;
        ans++;
        i=j-1;
    }
    for (int i=1;i<p1.size()-1;i++) {
        if (!is[p1[i].second]) continue;
        int pp1=-1,pp2=-1;
        int l=1,r=p2.size();
        while (l<=r) {
            int mid=(l+r)>>1;
            if (p2[mid-1].second<=p1[i].second) {
                pp1=mid-1;
                l=mid+1;
            }
            else {
                r=mid-1;
            }
        }
        l=1,r=p2.size();
        while (l<=r) {
            int mid=(l+r)>>1;
            if (p2[mid-1].second>=p1[i].second) {
                pp2=mid-1;
                r=mid-1;
            }
            else {
                l=mid+1;
            }
        }
        if (pp1==-1||pp2==-1) {
            continue;
        } 
        if (p2[pp1].first!=p2[pp2].first) continue;
        int j;
        for (j=i;j<p1.size()-1;j++) if (!is[p1[j].second]) break;
        int f=0;
        for (int k=i;k<j;k++) {
            if (p1[k].first!=p2[pp1].first&&p1[k+1].first!=p1[k-1].first) {
                f=1;
            }
        }
        if (f) ans++;
        i=j-1;
    }
    printf("%d
",ans);
}
原文地址:https://www.cnblogs.com/zhanglichen/p/14394550.html