洛谷 P3668 [USACO17OPEN]Modern Art 2 现代艺术2 栈

solution:栈

本篇题解是受到大佬qiianr的启发,如果侵权,请联系删除

  1. 为了保证最优解,我们必须要先涂最外层,举个例子:AAABCBBBA,(A,B,C分别代表一种颜色)我们先把这些都涂上A,然后中间都涂上B,最后再在最上面那一个涂上C,这就是最优解的情况

  2. 对于每个颜色,我们记录这个颜色的开始位置和结束位置,我们可以很清楚的看到越到最外层涂的颜色,开始位置越晚,结束位置越早,所以我们可以用一个栈来维护当前栈顶的颜色

  3. 并且我们涂的区间不能重叠,举个例子,A和B分别代表一种颜色:AABBAAB,根据上面所推得,我们应该找最外层的颜色,但是因为A和B重叠,所以这种情况是不合法的

  4. 枚举画条上的每一个点,对于一个颜色如果这个颜色的开始位置等于现在枚举的位置,那么我们就把这个颜色压入栈,如果当前颜色和栈顶颜色不同,那么我们直接输出无解即可

  5. 如何寻找答案,因为我们都把颜色放进栈中,所以我们只需要比较答案和栈内的元素个数,最后取最大值即可

  6. 如果当前枚举的点等于这个元素的结束位置,那么我们直接弹出栈顶即可

  7. 后一点,也没什么可说的,加一些优化,手打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;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值