算法沉淀第一天(Triple Removal)

目录

引言:

Triple Removal

        题意分析

        逻辑梳理

        代码实现

结语:


引言:

        家人们,天塌了,速通ACM省铜失败了,只能沉淀算法了,来年再战,接下来,C语言专栏的更新就恢复照常了

        今天是算法沉淀的第一天,先开个CF评级1400的题热热手,那么,我们废话不多说,就进入今天的题目讲解吧——————————>

     


Triple Removal

        那么,按照先前惯例

        题意分析

        这是题目链接Problem - 2152C - Codeforces

        不想跳转的可看下图

        这道题的意思很简单,就是给你一个数组,然后数组里面的元素不是1就是0

        然后再问你q次,每次问你从l到r的那一段数组可不可以通过操作来将这一块数组清空 

        然后如果可以,就输出最小的操作代价

        如果不可以,就输出-1

        然后具体每次怎么操作呢

                1.先选择3个下标i,j,k,这三个下标所对应的元素值要一样

                2.删除这三个元素,付出的操作代价是min(k-j,j-i),然后将删完数的数组再合并起来,不留空隙

        那么,题目分析完了,接下来就进入逻辑梳理环节


        逻辑梳理

        这题的逻辑其实还是比较好梳理的,一步步来就好了

        首先,如果这个数组区间的长度不是3的倍数,那么肯定输出-1,因为每次选择删除的个数都要为3个

        那么接下来接着想,还有什么情况会输出-1呢,那就是这个区间的数组中,1的个数或是0的个数不为3的倍数,因为每次要删的都是3个一样的数,所以如果1的个数和0的个数不是 3的倍数,那么就无法将所有数删完

        那么,接下来,不能删完的情况判断完了,接下来我们来判断能删完的情况下,最少的代价怎么算

        首先,因为他每次删除3个后都会压缩数组,所以,如果一开始有俩个一样的数相邻,就一定可以每次都进行1的损耗就删除3个元素

        而如果一开始没有俩个一样的数相邻,那么就只有01010101或者101010的情况,所以就是第一次删除的时候需要2的代价,之后也是1的代价

        那么逻辑梳理就梳理完啦,接下来进入代码实现的环节


        代码实现

        首先,代码实现过程中需要3个数组来分别存放0的个数的前缀和和1的个数的前缀和和相邻元素是一样的前缀和,如果不用这三个前缀和数组来进行存放,那么就会超时,我第一发就是因为没有相邻数的前缀和数组,导致代码TLE了,那么,接下来,就直接展现AC源码啦

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <queue>
using namespace std;

int t, n;
bool a[250010];
int zero[250010];
int one[250010];
int ling[250010];
void solve()
{
	int l, r;
	cin >> l >> r;
	if ((zero[r] - zero[l - 1]) % 3 || (one[r] - one[l - 1]) % 3)
	{
		cout << "-1" << endl;
		return;
	}
	int ans = 1;
	
	if (ling[r]-ling[l])
	{
		ans--;
	}
		
	ans += (r - l + 1) / 3;
	cout << ans << endl;
}

int main()
{
	cin >> t;
	while (t--)
	{
		memset(one, 0, sizeof(one));
		memset(zero, 0, sizeof(zero));
		memset(ling, 0, sizeof(ling));
		int q;
		cin >> n >> q;
		a[0] = -1;
		for (int i = 1; i <= n; i++)
		{
			cin >> a[i];
			if (a[i])
			{
				one[i] = one[i - 1] + 1;
				zero[i] = zero[i - 1];
			}
			else
			{
				one[i] = one[i - 1];
				zero[i] = zero[i - 1] + 1;
			}
			if (a[i] == a[i - 1])
				ling[i] = ling[i-1] + 1;
			else
				ling[i] = ling[i-1];
		}
		while (q--)
			solve();
	}
	return 0;
}

结语:

        今日算法讲解到此结束啦,希望对你们有所帮助,谢谢观看,如果觉得不错可以分享给朋友哟。有什么看不懂的可以评论问哦,这是真的最后一期啦

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值