您的位置:首页 > 其它

[NOIP2017模拟]art2

2017-08-26 11:52 176 查看
题目描述

奶牛贝茜已经厌倦了二维的绘画,于是她想要画更抽象的一维画。

她的画板是一个长度为 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,发现这是红色的右端点,t
4000
op–,红色出栈。

读到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;
}


本题结
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: