solution:栈
本篇题解是受到大佬qiianr的启发,如果侵权,请联系删除
-
为了保证最优解,我们必须要先涂最外层,举个例子:AAABCBBBA,(A,B,C分别代表一种颜色)我们先把这些都涂上A,然后中间都涂上B,最后再在最上面那一个涂上C,这就是最优解的情况
-
对于每个颜色,我们记录这个颜色的开始位置和结束位置,我们可以很清楚的看到越到最外层涂的颜色,开始位置越晚,结束位置越早,所以我们可以用一个栈来维护当前栈顶的颜色
-
并且我们涂的区间不能重叠,举个例子,A和B分别代表一种颜色:AABBAAB,根据上面所推得,我们应该找最外层的颜色,但是因为A和B重叠,所以这种情况是不合法的
-
枚举画条上的每一个点,对于一个颜色如果这个颜色的开始位置等于现在枚举的位置,那么我们就把这个颜色压入栈,如果当前颜色和栈顶颜色不同,那么我们直接输出无解即可
-
如何寻找答案,因为我们都把颜色放进栈中,所以我们只需要比较答案和栈内的元素个数,最后取最大值即可
-
如果当前枚举的点等于这个元素的结束位置,那么我们直接弹出栈顶即可
-
后一点,也没什么可说的,加一些优化,手打max,加个位运算快读,随手加个register,开O2 38ms,不开47ms,处于最优解第一页
AC代码
#include<cstdio>
#define si 100005
#define re register int
using namespace std;
int n,ans,tp,a[si],st[si],ed[si],sta[si];
inline int read() {
int x=0,cf=1;
char ch=getchar();
while(ch<'0'||ch>'9') {
if(ch=='-') cf=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*cf;
}
inline int max(int A,int B) { return A>B?A:B; }
int main() {
n=read();
for(re i=1;i<=n;i++) {
a[i]=read();
if(!st[a[i]]) st[a[i]]=i;//如果这个元素还没有开始位置,记录开始位置
ed[a[i]]=i;//随时记录结束位置
}
ed[0]=n+1,a[n+1]=0;
for(re i=0;i<=n+1;i++) {
int x=a[i];
if(i==st[x]) {//当前枚举等于开始位置,推入栈
sta[++tp]=x;
ans=max(ans,tp);//取最大值
}
if(x!=sta[tp]) {//当前元素和栈顶元素颜色不同,输出无解
printf("-1");
return 0;
}
if(i==ed[x]) tp--;//等于结束位置,弹出
}
printf("%d",ans-1);
return 0;
}