点击上方蓝字,关注并星标,和我一起学技术。

大家好,欢迎阅读周末算法题专题。

今天我们选择的是codeforces contest 1417的C题k-Amazing Numbers。这是一道经典的数据结构题,全场通过4700+,比以往的C题要稍稍难一些。有一些trick,解法不算很难,但是不太容易想到。


题目链接:https://codeforces.com/contest/1417/problem/C

我们废话不多说了,直接来看题。

题意

给定n个数构成的数字,我们定义一个k-amazing数的概念。如果数a同时出现在数组中所有k个连续元素构成的序列当中,并且a是其中最小的那个,那么就称为a是一个k-amazing数字。

我们抽象一下,其实有两个条件,第一个条件是同时出现。我们假设数组是[1, 2, 3, 4, 5],当k=3时,我们可以找到的序列是[1, 2, 3], [2, 3, 3], [3, 4, 5]。这三个序列当中的共有元素是3,并且只有3,所以3就是一个k-amazing数。第二个条件是最小,如果这样的数字可以找到多个,只有最小的那个数字才是k-amazing数。

现在给定数组a,要求所有的1-n的k-amazing数。

样例

首先输入一个整数t,表示测试数据组数()。

对于每组数据一共有三行输入,第一行输入为一个整数n()。

第二行输入n个整数。

要求输出一行整数,表示k=1到k=n时的所有k-amazing数,如果不存在则输出-1。


题解

这道题的题意倒是挺明确的,没什么含糊不清的情况。但是我们分析一下会发现,想要顺着题意去解决是不可能的。因为我们没有什么特别好的方法可以快速寻找多个集合当中的交集,并且查询到交集之后还需要分析交集当中的最小值。

也尝试过引入线段树或者是树状数组等数据结构,依然一无所获。最后能够解出来其实挺取巧的,是因为注意到了一个细节,这个细节就是元素的范围,题目当中给定的是。这和我们以往的题目都不太一样,一般来说都会给定一个具体的值作为范围,而不是给定一个变量。

如果有过一定算法题基础和经验的同学,注意到这个应该能想到桶排序或者是基数排序。如果我们保证所有的元素都小于数组的长度,那么我们可以用一种很取巧的方式来完成排序。

我们直接来看代码:

a = [4, 3, 2, 5, 1]ret = []base = [0 for _ in range(6)]

for i in a:    base[i] += 1

for i in range(6):    if base[i] > 0:        for j in range(base[i]):            ret.append(i)

这个算法的复杂度是,要比一般的排序算法更快,因为我们利用了下标的天然有序性。顺着这条线我想到了问题的关键,发现我们一开始的思路其实走入了误区。

思维误区与提示

这道题最大的trick就是我们对于算法的初印象,我一直在想一种方法可以快速地根据k求出k-amazing数。然后我发现情况非常复杂,并且涉及到集合的处理,比较麻烦。

这道题需要我们反其道而行之,并不是根据k去寻找k-amazing数,而是根据一个数在数组当中出现的分布,来判断它可以构成什么k-amazing。这也是为什么所有出现的数要小于n的原因,并不是说一定要小于n才有解,而是为了给我们一个思维提示。

我简单来解释一下这其中的原理,大家立刻就明白了,其实非常非常简单,有点像是魔术师用很简单的障眼法欺骗了我们的感觉。


我们假设上面这条线是题目给定的数组,我们假设其中某一个数m出现了3次,分别是a1, a2和a3。那么请问,如果m是一个k-amazing数,这个k应该至少是多大?

很简单,应该是,我们肉眼观察一下应该是a2-a1,那么我们画出来应该是这样的:


其实就是简单的区间覆盖问题,如果k小于这个值,那么a1到a2中间的部分一定无法满足。你可能还是会觉得有问题,不对啊,我们要找的是最小值,你怎么能知道这个m是不是最小的呢?

这个问题也非常简单,我们只需要按照顺序从小到大去寻找k,那么第一个找到的一定就是答案。想明白了之后有没有醍醐灌顶,有没有豁然开朗的感觉?是不是还有我居然想到了,又有一点觉得自己早就应该想到了的矛盾感?这也是做算法题的乐趣所在,所谓的难者不会,会者不难,体现得淋漓尽致。

不过还有一个小trick,有可能对于有些k我们找不到答案,但是它并不一定不存在。这也很好理解,我们假设找到了k=3时的答案是m,我们没有直接找到间隔是4的数,那么问题来了,m满不满足k=4呢?当然是满足的,因为小的间隔都能成立,大的间隔一定也可以。

最后,贴上代码:

from collections import defaultdict

t = int(input())

for _ in range(t):    n = int(input())    arr = list(map(int, input().split(' ')))    # 我们要记录元素的出现位置,会有多个,所以要用map[int]list的结构    dt = defaultdict(list)

    for i, v in enumerate(arr):        dt[v].append(i)

    ret = [-1 for _ in range(n+2)]

    for i in range(1, n+1):        if i not in dt:            continue

        # 由于下标是0开始的,所以第一段区间长度是下标+1        tmp = dt[i][0] + 1        # 寻找元素i出现的最大间隔        for idx in range(1, len(dt[i])):            tmp = max(tmp, dt[i][idx] - dt[i][idx-1])

        tmp = max(tmp, n - dt[i][-1])        # 如果这个长度的答案没有出现过,就赋值        if ret[tmp] == -1:            ret[tmp] = i

    # 如果m是k-amazing数,那么它也是k+1-amazing数    for i in range(2, n+1):        if ret[i-1] == -1:            continue        if ret[i] == -1 or ret[i] > ret[i-1]:            ret[i] = ret[i-1]

    print(' '.join(map(str, ret[1: n+1])))

这题非常有趣,强烈建议大家都试着做一下。

今天的文章就到这里,衷心祝愿大家每天都有所收获。如果还喜欢今天的内容的话,请来一个三连支持吧~(点赞、在看、转发)

- END -

怎么获取codeforces的数据_原创 | codeforces 1417C,逆向思考的数据结构题相关推荐

  1. HI3559V200获取IMX458摄像头数据_(2)sdk例程sample_vio

    文章目录 1.sample_vio介绍 1 linux client端 2 liteos server端 2.sample_vio_server如何在liteos运行 1.如何将sample_vio_ ...

  2. 怎么获取codeforces的数据_手把手教你学会新媒体运营——如何通过数据分析来优化新媒体运营...

    一般来说,我们希望运营的新媒体的每篇内容都可以获得高打开率和高分享率.但事实并不总是如愿,因此,在新媒体运营过程当中,我们需要不断地优化自身内容,以求可以获得更多的关注和流量.那么我们今天来讨论下如何 ...

  3. Request_获取请求行数据_方法介绍

    request功能:     1. 获取请求消息数据         1. 获取请求行数据             * GET /day14/demo1?name=zhangsan HTTP/1.1 ...

  4. android 简单获取实时天气数据_绘图本身很简单但是获取数据很难

    看到我们生信技能树的教学群有学员提问这样的图如何绘制: 其实我们讲解过,绘图代码本身搜索即可拿到,关键词 ggpubr paired boxplot ,输入到 https://cn.bing.com/ ...

  5. mysql fetchall获取不到数据_解决pymysql cursor.fetchall() 获取不到数据的问题

    1.之前的写法(不报错): data = cursor.fetchall() data_name = data[0]['task_type'] 2.简洁的写法(报错): data = cursor.f ...

  6. HI3559V200获取IMX458摄像头数据_(3)实例分析+问题解决

    文章目录 1.整体流程设计 2.模块分析 2.1 ipcm 2.2 VB初始化 2.3 vpss dump frame 2.4 YUV420SP转RGB 2.4.1 利用IVE转换出MMZ内存图像直接 ...

  7. 怎么获取codeforces的数据_飞瓜数据5大功能盘点,帮你抓住2019抖音新一波涨粉红利期!...

    在过去的一年中,短视频产业全面进入高速运作的模式,我们飞瓜数据为了更好的服务抖音短视频运营,覆盖抖音各个方面的数据,为抖音运营者提供从内容到电商运营整个产业链过程中所涉及的服务数据平台. 如何让更多用 ...

  8. pythonurllib库获取yahoo财经数据_金融数据的获取——一个爬虫的简单例子

    对量化投资策略进行研究,第一步就是获取我们需要的数据.使用历史数据能够对策略进行回测,以验证策略的有效性和可信性.另一方面,量化投资本身也是一种对数据的研究,因此它也必须遵循数据分析的相关步骤.作为一 ...

  9. c 获取mysql列数据_转 用C API 操作MySQL数据库

    用C API 操作MySQL数据库 参考MYSQL的帮助文档整理 这里归纳了C API可使用的函数,并在下一节详细介绍了它们.请参见25.2.3节,"C API函数描述". 函数 ...

最新文章

  1. 一文梳理视觉Transformer架构进展:与CNN相比,ViT赢在哪儿?
  2. RocketMQ NameServer网络通信架构(基于Netty)
  3. Codeforces 补题记录
  4. 安装zabbix4.0+grafana
  5. WebAPI(part11)--DOM重点核心
  6. 在Ubuntu 16.04环境下安装Docker-CE(附视频教程)
  7. 2016/1/14 java随机数生成
  8. [C# 基础知识梳理系列]专题四:事件揭秘
  9. line vty 0 4 和line vty 5 15 区别
  10. l2tp pptp相关的一些记录
  11. 【SPSS】第3讲学习笔记——数据导入和查看
  12. 光立方原理讲解_漯河放大镜原理,车灯透镜_晶亮光电
  13. Matlab里怎么注释掉一段(多行)代码
  14. SQL注入分类、防御
  15. pythonttf字体反爬虫_利用Python采集起点中文网小说,并解决字体反爬的问题
  16. 六子棋的程序(修改)
  17. 执行力:用良好的习惯,确保自己的执行力
  18. windows,ubuntu,代码三种方式制作Android开机动画 bootanimation.zip
  19. 【社区周会】2021-06-08 内容概要
  20. 1月书讯:Hello 2021! (上)

热门文章

  1. UEFI、BIOS、Secure Boot的关系和知识介绍
  2. 【HDOJ】4579 Random Walk
  3. PowerShell针对SCVMM批量导出模板的描述信息以及导入
  4. if...else if switch分支结构
  5. Visual Studio 2005 SQL Server 2005 are COMING!
  6. spring boot 应用设置session path_kubernetes configmap 热更新spring-boot应用
  7. jQuery 实现 select模糊查询 反射机制
  8. 两个rtsp同时抓流_海康摄像头同时添加到两台海康硬盘录像机上
  9. mysql connect 500_MySQL连接问题【mysql_connect和mysql_pconnect区别】
  10. linux 安装包 在此作用域中尚未声明_Linux运行go项目报错:copy_file_range: bad file descriptor...