Array Painting

Educational Codeforces Round 152 (Rated for Div. 2)
D. Array Painting
题目链接

题意:

给你一个由 n n n 个整数组成的数组,其中每个整数都是 0 0 0 1 1 1 2 2 2 。最初,数组中的每个元素都是蓝色的。

您的目标是将数组中的每个元素涂成红色。为此,您可以执行两种类型的操作:

  • 支付一枚硬币,选择一个蓝色元素并将其涂成红色;
  • 选择一个不等于 0 0 0 的红色元素和一个与之相邻的蓝色元素,将所选的红色元素减少 1 1 1 ,并将所选的蓝色元素涂成红色。

要实现目标,你最少需要花费多少金币?

思路:

如果我们把连续的非零部分看作一个部分,那么如果这个部分里只有1,它就只能吸收一边的一个0。如果这个部分有2,那么它可以吸收两边各一个0。这一个区间只花1块钱。

假设我们规定一个区间只吸收一个0的话,先吸收左边的,没有再吸收右边的,所以用双指针从左到右看。其实无外乎四种情况:

  1. 0 非零区间 0
  2. 0 非零区间
  3. 非零区间 0
  4. 0 0

第二种情况其实是不存在的,因为后面没0的话可以一直走到结尾,所以我们把第 n + 1 n+1 n+1 个数看成 0 0 0 就可以了,这样就不存在第二种情况了。所以就是如果 l l l 是个 0 0 0 就让 r r r l + 1 l+1 l+1 向后找第二个 0 0 0,如果中间的非零区间有 2 2 2,就吃掉后面的 0 0 0 l l l 指向 r + 1 r+1 r+1。如果没有 2 2 2 就指向 r r r。如果l是个非0数,也是向后找,不过后面的 0 0 0 一定可以吃掉,直接指向 r + 1 r+1 r+1 即可。

code:

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=2e5+5;

int n,a[maxn],ans;

int main(){
	cin>>n;
	for(int i=1,t;i<=n;i++)
		cin>>a[i];
	
	bool f;
	for(int l=1,r,maxx;l<=n;l=r){
		maxx=0;
		r=l+(f=a[l]==0);
		while(a[r]!=0)
			maxx=max(maxx,a[r++]);
		if(maxx==2 || !f)r++;
		ans++;
	}
	cout<<ans;
	return 0;
}

思路2:

队友的思路,把找区间的操作和累加操作拆开,就是先缩点,再找答案。把上面说的非零区间缩成一个数,有2的区间缩成2,没2的缩成1,之后和上面的想法一样,先吃掉左边的0,吃不到或者能吃两个就把右边的0吃掉,被吃掉的0标记为-1。最后数一下非-1的数的个数就好了。

code:

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=2e5+5;

int n,a[maxn],ans;
int b[maxn],cnt;

int main(){
	cin>>n;
	for(int i=1,t;i<=n;i++)
		cin>>a[i];
	
	for(int i=1,maxx;i<=n;i++){//缩点 
		if(a[i]==0)b[++cnt]=0;
		else {
			maxx=a[i];
			while(a[i+1]!=0){
				i++;
				maxx=max(maxx,a[i]);
			}
			b[++cnt]=maxx;
		}
	}
	
	b[0]=b[cnt+1]=-1;
	for(int i=1;i<=cnt;i++){
		if(b[i]==1){
			if(b[i-1]==0)b[i-1]=-1;
			else b[i+1]=-1;
		}
		if(b[i]==2){
			b[i-1]=b[i+1]=-1;
		}
	}
	for(int i=1;i<=cnt;i++)
		if(~b[i])
			ans++;
	cout<<ans;
	return 0;
}
  • 22
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值