【AcWing每日一题】4261. 孤独的照片

news2024/11/14 2:31:57

Farmer John 最近购入了 N 头新的奶牛,每头奶牛的品种是更赛牛(Guernsey)或荷斯坦牛(Holstein)之一。

奶牛目前排成一排,Farmer John 想要为每个连续不少于三头奶牛的序列拍摄一张照片。

然而,他不想拍摄这样的照片,其中只有一头牛的品种是更赛牛,或者只有一头牛的品种是荷斯坦牛——他认为这头奇特的牛会感到孤立和不自然。

在为每个连续不少于三头奶牛的序列拍摄了一张照片后,他把所有「孤独的」照片,即其中只有一头更赛牛或荷斯坦奶牛的照片,都扔掉了。

给定奶牛的排列方式,请帮助 Farmer John 求出他会扔掉多少张孤独的照片。

如果两张照片以不同位置的奶牛开始或结束,则认为它们是不同的。

输入格式
输入的第一行包含 N。

输入的第二行包含一个长为 N 的字符串。如果队伍中的第 i 头奶牛是更赛牛,则字符串的第 i 个字符为 G。否则,第 i 头奶牛是荷斯坦牛,该字符为 H。

输出格式
输出 Farmer John 会扔掉的孤独的照片数量。

数据范围
3≤N≤5×105
输入样例:

5
GHGHG

输出样例:

3

样例解释
这个例子中的每一个长为 3 的子串均恰好包含一头更赛牛或荷斯坦牛——所以这些子串表示孤独的照片,并会被 Farmer John 扔掉。

所有更长的子串(GHGH、HGHG 和 GHGHG)都可以被接受。

自己的思路:

  • 输入字符串之后记录两种牛的种类的数量
  • 对于每一个子字符串,查看这个字符串剩下的牛的数量是否符合
  • 如果某一种牛的数量为1,那么这一组照片应该被扔掉
#include<iostream>
using namespace std;

const int N = 5e5+10;
int n, h = 0, g = 0, res = 0, sum = 1;
char str[N];
int main(){	
	cin >> n;
	scanf("%s", str);
	for(int i = 0; i < n; i++){		
		if(str[i] == 'H') h++;
		if(str[i] == 'G') g++;
	} 
	int sumh = h, sumg = g;
	for(int i = 0; i < n; i++){
		int sg = sumg, sh = sumh; 
		for(int j = n-1; j >= i+2; j--){
			if(sg == 1 || sh == 1)		//如果其中有一种牛的数量是1 
				res++;					//扔掉的孤独的照片数量加一 
			if(sg == 0 || sh == 0)		//如果某一种牛的数量为0 
				break;					//没有能使得照片扔掉的序列,剪枝 
			//如果没有牛的数量是1
			if(str[j] == 'G') sg--;		//把后面这种牛的数量减掉,指针前移 
			if(str[j] == 'H') sh--;
			
		}
		if(str[i] == 'G') sumg--;		//把前面这种牛的数量减掉,指针后移 
		if(str[i] == 'H') sumh--;
	}	
	cout << res;	
	return 0;
}

问题很显然,这样会在任何情况下的时间复杂度都是O(n2)
这样在内层的for循环加入剪枝

if(sg == 0 || sh == 0)		//如果某一种牛的数量为0 
	break;					//没有能使得照片扔掉的序列,剪枝 

会在部分较好情况下把时间复杂度降一点,最好的时间复杂度为O(n)
但是在较坏的情况下,还是有很高的复杂度
还有个问题就是res的数量级用int是存不下的,需要long long

//测试复杂度的代码:
	cin >> n;
//	scanf("%s", str);
	for(int i = 0; i < n; i++){	
		if(i%2 == 0) str[i] = 'G';
		else str[i] = 'H';
//		str[i] = 'H';	
		if(str[i] == 'H') h++;
		if(str[i] == 'G') g++;
	} 

y总的方法:

  • 因为要扔掉的图片中有一个字母只出现一次,所以我们可以去枚举只出现一次的图片是哪一个
  • 我们要找的是,只包含一个G或H的、长度大于等于三的字串的数量
  • 符合要求的字符串只能包含一个G或H,所以其他位置是另外一个字母
  • 枚举每一个位置,会出现三种情况

对于每一个位置的字母,在字串的长度大于等于三的情况下

  1. 左边和右边至少存在一个不同于当前位置的字母。设左边有L个,右边有R个,那么左边和右边分别可以取1,2,…,L个,1,2,…,R个(这种情况至少一边取一个)。那么这种情况符合乘法原理,一共是L*R种情况。
  2. 左边没有不同于当前位置字母的字母。那这种情况只能从右边取。同样设右边有R个(不同于当前位置字母的字母),那么可以取2,3,…,R个,有R-1种情况
  3. 右边没有不同于当前位置字母的字母。那这种情况只能从左边取。同样设左边有L个(不同于当前位置字母的字母),那么可以取2,3,…,L个,有L-1种情况

最后把这三种情况加起来就是答案,并且这种方法的时间复杂度为O(n)

举个例子:
y总的图
假设枚举到某一个位置时,当前位置的字母为G,那么想要得到符合条件的结果,只能从其他地方取H

  1. 对于上面的第一种情况,左边可以取1,2,…,L个H,右边可以取1,2,…,R个H,符合乘法原理
  2. 对于第二种情况,只能从右边取H但是至少取两个
  3. 对于第三种情况,之能从左边取,最少两个

附上代码:

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N = 500010;

int n;
char str[N];
int l[N], r[N];		//表示左边和右边有多少个与当前位置不一样的连续的字母

int main()
{
    scanf("%d", &n);
    scanf("%s", str);
	//先处理左边
    for (int i = 0, h = 0, g = 0; i < n; i ++ )
        if (str[i] == 'G') l[i] = h, h = 0, g ++ ;	//当前位置存的G,记录左边扫过的连续的H的数量,连续h的数量就被清空了,开始加g的数量
        else l[i] = g, g = 0, h ++ ;				//当前位置存的H,记录左边扫过的连续的G的数量,连续g的数量就被清空了,开始加h的数量
	//再处理右边
    for (int i = n - 1, h = 0, g = 0; i >= 0; i -- )
        if (str[i] == 'G') r[i] = h, h = 0, g ++ ;
        else r[i] = g, g = 0, h ++ ;
	//所有的情况加起来
    LL res = 0;
    for (int i = 0; i < n; i ++ )
        res += (LL)l[i] * r[i] + max(l[i] - 1, 0) + max(r[i] - 1, 0);

    printf("%lld\n", res);
    return 0;
}
//
//作者:yxc
//链接:https://www.acwing.com/activity/content/code/content/5012677/
//来源:AcWing
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/132336.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java多线程(11):线程协作

1 线程通信 应用场景 : 生产者和消费者问题 假设仓库中只能存放一件产品 , 生产者将生产出来的产品放入仓库 , 消费者将仓库中产品取走消费 如果仓库中没有产品 , 则生产者将产品放入仓库 , 否则停止生产并等待 , 直到仓库中的产品被消费者取走为止 如果仓库中放有产品 ,…

Chrome Extension 基础篇

Extensions are software programs, built on web technologies (such as HTML, CSS, and JavaScript) that enable users to customize the Chrome browsing experience. 扩展程序是基于 Web 技术&#xff08;例如 HTML、CSS 和 JavaScript&#xff09;构建的软件程序&#xf…

C语言递归

递归指的是在函数的定义中使用函数自身的方法。 举个例子&#xff1a; 从前有座山&#xff0c;山里有座庙&#xff0c;庙里有个老和尚&#xff0c;正在给小和尚讲故事呢&#xff01;故事是什么呢&#xff1f;"从前有座山&#xff0c;山里有座庙&#xff0c;庙里有个老和尚…

redis的安装

1.Redis是基于C语言编写的&#xff0c;因此首先需要安装Redis所需要的gcc依赖&#xff1a; yum install -y gcc tcl2.上传安装包并解压 tar -xzf redis-6.2.6.tar.gz3.解压后&#xff0c;进入redis目录 cd redis-6.2.64.运行编译命令 make && make install如果没有…

3_运行时数据区概述及线程

前言 本节主要讲的是运行时数据区&#xff0c;也就是下图这部分&#xff0c;它是在类加载完成后的阶段 当我们通过前面的&#xff1a;类的加载-> 验证 -> 准备 -> 解析 -> 初始化 这几个阶段完成后&#xff0c;就会用到执行引擎对我们的类进行使用&#xff0c;同时…

56. 数据增广 / 图像增广

1. CES上的真实故事 2. 数据增强 增加一个已有数据集&#xff0c;使得有更多的多样性 在语言里加入各种不同的背景噪音改变图片的颜色和形状 例如&#xff0c;我们可以以不同的方式裁剪图像&#xff0c;使感兴趣的对象出现在不同的位置&#xff0c;减少模型对于对象出现位置…

Linux系统如何添加磁盘分区基本情况

Linux系统如何添加磁盘&&分区基本情况 原理介绍 Linux来说无论有几个分区&#xff0c;分给哪一目录使用&#xff0c;它归根结底就只有一个根目录&#xff0c;一个独立且唯一的文件结构&#xff0c;Linux中每个分区都是用来组成整个文件系统的一部分。 Linux采用了一种…

JavaScript-DOM和BOM详解

文章目录DOM 和 BOM1. DOM2. BOM2.1 BOM 简介2.2 分类2.3 语法1) Navigator 当前浏览器2&#xff09;Histry 向前或向后翻页3&#xff09;Location 地址栏的信息DOM 和 BOM 1. DOM 浏览器已经为我们提供了文档节点的对象&#xff0c;这个对象是 window 对象的属性可以在页面中…

Netconf协议讲解

目录 什么是Netconf 为什么要提出Netconf 数据的类别 传统网络配置协议 Netconf配置协议 Netconf协议架构 安全传输层 消息层 操作层 内容层 Netconf配置设备流程 通过Python进行Netconf配置 什么是Netconf NETCONF&#xff08;Network Configuration Protocol&…

Unity运行时代码编辑插件介绍-InGame Code Editor-IDE类文本编辑器

因为某些原因,需要在Runtime显示一下代码,也方便做样式设计 所以找到了这个插件 特色什么的都不展开说了,开源的代码都是好代码,样式什么的就不能要求过多 基础使用方法 导入TextMeshPro 基于这个插件的,所以需要先从Package Manager先下载TextMeshPro 创建编辑器 T…

【SpringBoot应用篇】SpringBoot集成j2cache二级缓存框架

【SpringBoot应用篇】SpringBoot集成j2cache二级缓存框架j2cache介绍j2cache入门使用pomapplication.ymlcaffeine.propertiesCacheTestController启动类j2cache介绍 j2cache是OSChina(开源中国)目前正在使用的两级缓存框架。 j2cache的两级缓存结构&#xff1a; L1&#xff…

《悠悠岁月》悠悠岁月,浅藏浅忆,且行且珍惜

《悠悠岁月》悠悠岁月&#xff0c;浅藏浅忆&#xff0c;且行且珍惜 安妮埃尔诺&#xff0c;法国当代著名女作家&#xff0c;2022年获诺贝尔文学奖。埃尔诺从1974年开始创作&#xff0c;至今已出版了约十五部作品。《悠悠岁月》这部历经二十余年思考和推敲的杰作&#xff0c;使她…

Apache Shiro(一)

1.Apache Shiro Apache Shiro Reference Documentation | Apache Shiro Apache Shiro 是一个功能强大且易于使用的 Java 安全(权限)框架。Shiro 可以完 成&#xff1a;认证、授权、加密、会话管理、与 Web 集成、缓存 等。借助 Shiro 您可以快速轻松 地保护任何应用程序——从最…

PHPExcel基本使用(2) 导入图片

一、效果二、代码一、效果 基于这篇 PHPExcel基本使用&#xff08;2&#xff09; 导入图片 调整 二、代码 基于thinkphp5.1 <?phpnamespace app\index\controller;use think\facade\Env;class Test {public function test(){self::excelAction();}/*** todo 导出报表*…

Microcontent - 微内容

这两年&#xff0c;微内容不断被人提及。微内容是什么&#xff1f;微内容解决什么问题&#xff1f;今天我们一起来看看这个话题。 作者&#xff1a;Sarah Cuellar - 1 - 什么是微内容 什么是微内容&#xff1f;微内容指的是小块的内容&#xff0c;它们遵循具体的的结构规则…

classnames 源码学习笔记与解读

前言 这里我引用源码文档中的一句话来作为开场白&#xff1a; A simple JavaScript utility for conditionally joining classNames together. 话不多说&#xff0c;咱们直接开始 classnames 的源码学习。 核心源码解读 直接来看它的源码部分&#xff0c;以下这是 classnam…

Win10的几个实用技巧系列之win10和win8系统哪个好用、系统任务栏和窗口假死的解决方法

目录 win10系统任务栏和窗口假死怎么办?win10系统任务栏和窗口假死的解决方法 win10系统任务栏和窗口假死怎么解决 Win10进不去Epic下载的死亡搁浅怎么办?Win10玩死亡搁浅闪退的解决方法 Epic领取的死亡搁浅进不去 Win10玩死亡搁浅闪退的解决方法 win10和win8系统哪个好用…

Eth09- EthCtrlConfig:以太网控制器写MAC地址到NVM中的配置

文章目录 1 MAC地址保存到非易失性存储器中传送门 ==>> AutoSAR入门和实战系列总目录 1 MAC地址保存到非易失性存储器中 如果想把MAC地址保存到非易失性存储器中,防止掉电之后MAC地址不存在了,可以通过以下的配置参数,实现实时保存MAC地址到NVM中 EthCtrlConfig/…

【Effective Objective - C】—— 读书笔记(四)

【Effective Objective - C】—— 读书笔记&#xff08;四&#xff09; 协议与分类 文章目录【Effective Objective - C】—— 读书笔记&#xff08;四&#xff09;协议与分类23.通过委托与数据源协议进行对象间通信要点&#xff1a;24.将类的实现代码分散到便于管理的数个分类…

Friedman 检验后的two-tailed Nemenyi test和the two-tailed Bonferroni-Dunn test的关键值

Critical values qαq_{\alpha}qα​ for post-hoc tests after the Friedman testCritical values qαq_{\alpha}qα​ for the two-tailed Nemenyi test Critical values qαq_{\alpha}qα​ for the two-tailed Bonferroni-Dunn test 其中classifiers是比较的方法个数&#…