[NOIP2017模拟]art2

来源:互联网 发布:80端口被攻击 编辑:程序博客网 时间:2024/06/05 01:15

题目描述
奶牛贝茜已经厌倦了二维的绘画,于是她想要画更抽象的一维画。
她的画板是一个长度为 N 的序列,一开始每个位置的颜色都是 0,表示空白,她有 N 种颜料,颜色编号分别为为 1~N,每次她会选择一种颜料,然后选择一个区间,把这个区间的所有位置全部涂成这个颜色(当然,后涂的颜色会覆盖先涂的颜色),她会进行恰好 N次这样的操作,每种颜料会且仅会用一次。
邪恶的奶牛月网想要抄袭贝茜的大作,她按这样的顺序作画:每次操作,她会选择一些不相交的区间,然后分别给每个区间涂上某种颜色(同样地,后涂的颜色会覆盖先涂的颜色)
在整个过程中,每种颜色只能被用来涂不超过一个区间(不一定所有颜色都要用)。现在,月网想知道,她至少需要多少次操作来完成她的计划?

输入格式
第一行一个整数 N(N<=100000) ,接下来 N 行,每行一个整数,表示贝茜的画作中第 i个位置的颜色。

输出格式
输出月网要复制贝茜的画,最少需要的操作数(如果她无法完成,输出-1)

样例数据
输入
7
0
1
4
5
1
3
3
输出
2

备注
【样例解释】
在第一组样例中,月网首先选择[2,5]和[6,7]这两个区间,分别涂上颜色1 和 3。
然后选择[3,3]和[4,4]这两个区间,分别涂上颜色 4和 5。
(当然也有其它方案,但都至少需要两次操作)

【数据范围】
30%的数据:N<=500
50%的数据: ,N<=10000
100% 的数据:N<=100000。

分析:先扫一遍,存下整个链,并记录每种颜色的起始和终止位置。然后进行扫描,做出栈入栈操作,详细操作如下:
样例如图所示:
这里写图片描述
进行出栈入栈操作
读到0,白色不管;
读到1,发现这是红色的左端点,入栈,top++,意思是颜色叠了一层,更新ans,即需要至少涂一次。
读到4,发现这是绿色的左端点,入栈,top++,更新ans,又发现它是右端点,因为几个不重叠的颜色区间是可以一起涂的,所以top–,绿色出栈。
读到5,发现这是蓝色的左端点,入栈,top++,因为和绿色相当于是同一层的颜色,和绿色一起涂,top是相同的,所以ans不更新,又发现它是右端点,top–,蓝色出栈。
读到1,发现这是红色的右端点,top–,红色出栈。
读到3,发现这是黄色的左端点,入栈,top++。
读到3,发现这是,黄色的右端点,top–,黄色出栈。
可以把这个栈想成一个立体图:
这里写图片描述
栈的top相同的颜色就在同一层,可以一起涂,而操作次数就是top最大值。
而无解的情况就是出现了类似这里写图片描述的排列,因为每种颜色只能用一次,所以这种情况无论先涂哪一个都会被后一个覆盖一半,输出-1。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<string>#include<ctime>#include<cmath>#include<algorithm>#include<cctype>#include<iomanip>#include<queue>#include<set>using namespace std;int getint(){    int sum=0 ,f=1;    char ch;    for(ch=getchar();(ch>'9'||ch<'0')&&ch!='-';ch=getchar());    if(ch=='-')    {        f=-1;        ch=getchar();       }    for(;ch>='0'&&ch<='9';ch=getchar())        sum=(sum<<3)+(sum<<1)+ch-'0';    return sum*f;}const int maxn=1e5+10;int n,ans,top,a[maxn],sta[maxn],maxl[maxn],maxr[maxn];int main(){    freopen("art2.in","r",stdin);    freopen("art2.out","w",stdout);    n=getint();    for(int i=1;i<=n;++i)    {        a[i]=getint();        if(a[i]==0)            continue;        if(maxl[a[i]]==0)            maxl[a[i]]=i;        maxr[a[i]]=i;    }    for(int i=1;i<=n;++i)    {        if(i==maxl[a[i]])        {            sta[++top]=a[i];            ans=max(ans,top);        }        if(i==maxr[a[i]])        {            if(sta[top]==a[i])                --top;            else            {                printf("-1\n");                return 0;            }        }    }    printf("%d\n",ans);    return 0;}

本题结