[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。
代码
本题结
奶牛贝茜已经厌倦了二维的绘画,于是她想要画更抽象的一维画。
她的画板是一个长度为 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; }
本题结
相关文章推荐
- JZOJ 5230. 【NOIP2017模拟A组模拟8.5】队伍统计
- JZOJ 5371. 【NOIP2017提高A组模拟9.17】组合数问题
- 【jzoj5232】【NOIP2017模拟A组模拟8.5】【带权排序】【线段树】
- [NOIP2017模拟]跳高
- 【JZOJ 5390】【NOIP2017提高A组模拟9.26】逗气
- 【jzoj5289】【NOIP2017提高组A组模拟8.17】【偷笑】【数据结构】
- 【jzoj5290】【NOIP2017提高组A组模拟8.17】【行程的交集】
- [jzoj5307]【NOIP2017提高A组模拟8.18】偷窃
- JZOJ5400. 【NOIP2017提高A组模拟10.7】Repulsed
- jzoj5331 【NOIP2017提高A组模拟8.23】壕游戏
- 【JZOJ5335】【NOIP2017提高A组模拟8.24】早苗
- 【JZOJ4920】【NOIP2017提高组模拟12.10】降雷皇
- 【JZOJ 4923】【NOIP2017提高组模拟12.17】巧克力狂欢
- JZOJ 5405. 【NOIP2017提高A组模拟10.10】Permutation
- JZOJ 5344. 【NOIP2017模拟9.3A组】摘果子
- 2017NOIP普及模拟赛题解报告
- jzoj5347. 【NOIP2017提高A组模拟9.5】遥远的金字塔 容斥
- [NOIP2017模拟]Tree
- noip 2017 模拟 D1 T3
- [NOIP2017模拟]count