| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> Codeforces Round #760 (Div. 3) 题解 完整A~G -> 正文阅读 |
|
[数据结构与算法]Codeforces Round #760 (Div. 3) 题解 完整A~G |
A. Polycarp and Sums of Subsequences题意有数组 a a a,由3个正整数组成。对于 a a a的每个非空子序列,求子序列中的元素和,并按非递减的顺序存入数组 b b b,显然 b b b由7个正整数组成。现给定数组 b b b,求数组 a a a。 思路不妨令 a = [ x , y , z ] , x ≤ y ≤ z a=[x,y,z],x\le y\le z a=[x,y,z],x≤y≤z,则 b = { x , y , z , x + y , y + z , z + x , x + y + z } b=\{x,y,z,x+y,y+z,z+x,x+y+z\} b={x,y,z,x+y,y+z,z+x,x+y+z}(并排序)。由于 x , y , z x,y,z x,y,z都是正整数,我们不难想到 x , y ≤ z , x + y , y + z , z + x ≤ x + y + z x,y\le z,x+y,y+z,z+x\le x+y+z x,y≤z,x+y,y+z,z+x≤x+y+z。因此 b b b中前两项必然是 x , y x,y x,y,最后一项必然是 x + y + z x+y+z x+y+z。 时间复杂度O ( 1 ) O(1) O(1) AC代码
B. Missing Bigram题意有一长为 n n n字符串,由小写字母’a’和’b’组成,现在依次将相邻的字母(第1个和第2个,第2个和第3个,依次类推)组成字母对,并删掉其中一对字母对,其余的字母对按顺序给出,求可能的原字符串。(任意输出一种答案) 思路假如不考虑删掉的那一对字母对,我们不难发现相邻字母对之间存在关系:前一字母对的后一个字母与后一字母对的前一个字母是相同的。因此,对于满足条件的相邻字母对,我们直接将其合并即可,否则,在这个位置一定删除了一个字母对,将其补上即可。如果整个字母对序列都处理完后仍没发现缺失,则我们可以在两端补上a或b中的任何一个字母(因为题目要求输出任何一种可行解),目的是为了补足字符串长度。 时间复杂度O ( n ) O(n) O(n) AC代码
C. Paint the Array题意现有一长度为 n n n的正整数数组 a a a,需要对其涂色。任选一正整数 d d d,并将 a a a中整除 d d d的数涂成红色,否则涂成蓝色。问是否存在一个正整数 d d d,使得涂色后数组中的相邻元素的颜色不相同。若存在,输出任一可行的 d d d,若不存在,输出0。 思路对题意作进一步的转化,我们会发现,题目要求我们选择一个正整数 d d d,使得 a a a中的奇数位置的元素都整除 d d d,而偶数位置的元素都不被 d d d整除(以下叙述建立在上述情况的假设之下),或是与之相反。 关于如何选择 d d d:由于奇数位置都能整除 d d d,那么 d d d一定是奇数位置元素的公约数,而 d d d中因子越多,越不容易被偶数位置的数整除,因此我们选择奇数位置元素的最大公约数。 由于 d d d已经确定,我们只需对偶数位置逐一验证是否被 d d d整除即可,若能满足条件则输出答案,若两种情况都不满足,说明无解,输出0。 时间复杂度O ( n log ? 2 a i ) O(n\log_2a_i) O(nlog2?ai?) AC代码
D. Array and Operations题意现有一长度为 n n n的正整数数组 a a a,要求你进行恰好 k k k次操作,每次操作可以选择 a a a中任意两个元素 a i a_i ai?和 a j a_j aj?,并将 ? a i a j ? \lfloor\frac{a_i}{a_j}\rfloor ?aj?ai???加入你的得分,然后删除这两个元素。完成 k k k次操作之后,将剩余元素也加入你的得分,求你的最小得分。 思路你的目标是使得分数尽可能的小,因此我们选择 a i a_i ai?和 a j a_j aj?之后,总有 0 ≤ ? a i a j ? ≤ 1 0\le\lfloor\frac{a_i}{a_j}\rfloor\le1 0≤?aj?ai???≤1。其次,我们一定选择最大的 2 ? k 2\cdot k 2?k个元素,因为如果我们放弃较大的某个数,而选择较小的某个数,我们最多能使得 ? a i a j ? \lfloor\frac{a_i}{a_j}\rfloor ?aj?ai???减小1,而剩余的元素之和至少会增加1,这一定不优于我们刚才的选择。最后我们要尽可能的避免 ? a i a j ? = 1 \lfloor\frac{a_i}{a_j}\rfloor=1 ?aj?ai???=1的出现,也就是说需要把相同的元素尽可能的不组合在一起,将数组从大到小排序后,我们将 a i a_i ai?和 a i + k a_{i+k} ai+k?组成一对,并产生 ? a i + k a i ? \lfloor\frac{a_{i+k}}{a_i}\rfloor ?ai?ai+k???,即是最优解。 时间复杂度O ( n log ? 2 n ) O(n\log_2n) O(nlog2?n)
E. Singers’ Tour题意有 n n n个城市 ( 1 , 2 , 3 , … , n ) (1,2,3,\dots,n) (1,2,3,…,n)按顺序环状排列(即城市 n n n的下一个城市是城市1),每个城市有一个歌手,第 i i i个城市的歌手会首先在城市 i i i开一场时长为 a i a_i ai?的音乐会( a i a_i ai?是正整数),然后前往下一个城市,每到一个新的城市他都会开音乐会,时长比上一个城市长 a i a_i ai?。所有歌手都开完音乐会之后,第 i i i个城市的音乐会总时长为 b i b_i bi?。现已知所有 b i b_i bi?,求所有的 a i a_i ai?,或反馈无解。 思路第一步,我们可以根据题目意思列方程:对第 i i i个城市, b i = 1 ? a i + 2 ? a i + 1 + ? + ( n ? 1 ) ? a i ? 2 + n ? a i ? 1 b_i=1\cdot a_i+2\cdot a_{i+1}+\dots+(n-1)\cdot a_{i-2}+n\cdot a_{i-1} bi?=1?ai?+2?ai+1?+?+(n?1)?ai?2?+n?ai?1?。 第二步,根据第一步的方程,求和: ∑ i = 1 n b i = ( ∑ i = 1 n i ) ? ( ∑ i = 1 n a i ) \sum_{i=1}^{n}b_i=(\sum_{i=1}^{n}i)\cdot(\sum_{i=1}^{n}a_i) ∑i=1n?bi?=(∑i=1n?i)?(∑i=1n?ai?)。等式左边的每一项都已知,而右边的 ∑ i = 1 n i \sum_{i=1}^{n}i ∑i=1n?i,实际上根据等差数列求和公式可以转化为 n ? ( n + 1 ) 2 \frac{n\cdot(n+1)}{2} 2n?(n+1)?。故可以解得 ∑ i = 1 n a i = 2 ∑ i = 1 n b i n ? ( n + 1 ) \sum_{i=1}^{n}a_i=\frac{2\sum_{i=1}^{n}b_i}{n\cdot(n+1)} ∑i=1n?ai?=n?(n+1)2∑i=1n?bi??。 第三步,根据第一步的方程,作差: b i ? b i ? 1 = a 1 + a 2 + ? + ( 1 ? n ) a i + ? + a n = ( ∑ i = 1 n a i ) ? n ? a i b_i-b_{i-1}=a_1+a_2+\dots+(1-n)a_i+\dots+a_n=(\sum_{i=1}^{n}a_i)-n\cdot a_i bi??bi?1?=a1?+a2?+?+(1?n)ai?+?+an?=(∑i=1n?ai?)?n?ai?。解此方程得 a i = 2 ∑ i = 1 n b i n ? ( n + 1 ) ? ( b i ? b i ? 1 ) n a_i=\frac{\frac{2\sum_{i=1}^{n}b_i}{n\cdot(n+1)}-(b_i-b_{i-1})}{n} ai?=nn?(n+1)2∑i=1n?bi???(bi??bi?1?)?。 注意 a i a_i ai?是正整数,需要考虑整除问题和0与负数问题。 时间复杂度O ( n ) O(n) O(n) AC代码
F. Reverse题意给定一个正整数 x x x,允许进行若干次操作:将 x x x转化为二进制形式,且不得含有前导零,在其末尾增加一个0或1,然后首尾对称翻转(不是翻转01,是翻转位置),去掉前导零,转化为十进制,替换原来的 x x x。问经过若干次(可能0次)操作后, x x x能否变成 y y y? 思路由于翻转之前,二进制的首位一定是1,故翻转后末位一定是1。又由于翻转后去掉所有前导0,故翻转后首位也是1。对于一个首尾都是1的二进制数 x x x来说,在其末尾增加一个0,然后翻转,得到的结果是 x x x的翻转(记作 x ˉ \bar{x} xˉ);如果在其末尾加一个1,然后翻转,则会得到 1 x ˉ 1\bar{x} 1xˉ。进而推广可得,经过若干次操作, x x x可以变成 111..1 x 111..1 111..1x111..1 111..1x111..1或 111..1 x ˉ 111..1 111..1\bar{x}111..1 111..1xˉ111..1,即左右侧会增加任意多个1(也可以是0个),这可以用归纳法证明。 此时会有一种个例,也就是第一次操作。由于一开始 x x x的末尾可能有0,归纳法失效,需要单独讨论。记初始时 x = x ′ 000..0 x=x'000..0 x=x′000..0,其中 x ′ x' x′的首尾都是1。如果在末尾加0,翻转后得到 x ′ ˉ \bar{x'} x′ˉ;如果在末尾加1,则翻转后会得到 1000..0 x ′ ˉ 1000..0\bar{x'} 1000..0x′ˉ,也可以认为是 1 x ˉ 1\bar{x} 1xˉ。 综合上述分析,最终可能得到的 y y y一定是以下5种可能中的一种:
对于前4种情况,由于一个数的二进制表示不会超过62位,我们直接暴力匹配即可。 时间复杂度O ( log ? 2 x log ? 2 y ) O(\log_2x\log_2y) O(log2?xlog2?y) AC代码
G. Trader Problem题意你手里有 n n n个物品,第 i i i个价值为 a i a_i ai?。另有 m m m个物品,第 i i i个价值为 b i b_i bi?。你可以把你手里的价值为 x x x的物品与不属于你的价值不超过 x + k x+k x+k的物品进行交换,交换后原本属于你的物品不再属于你并且可以在新的交换中被换回来,而作为交换,原本不属于你的那个物品现在属于你并且可以被用于新的交换中。现在有 q q q次询问,给定 k k k,求经过任意次数交换后属于你的物品的价值的最大值。 思路首先我们考虑一种朴素的做法: 假设 k k k已经确定,我们需要求出此情形下最终的最大价值。 将所有物品(包括属于你的和不属于你的)按价值从大到小排序,第 i i i个价值为 v i v_i vi?,然后依次遍历每一个物品。对于第 i i i件物品,如果存在 j ∈ [ i , n + m ] j\in[i,n+m] j∈[i,n+m],满足对任意 p ∈ [ i , j ? 1 ] p\in[i,j-1] p∈[i,j?1],有 v p ? v p + 1 ≤ k v_p-v_{p+1}\le k vp??vp+1?≤k,且第 j j j个物品当前属于你,那么经过若干次交换,我们可以间接或直接地用价值为 v j v_j vj?的物品交换得到价值为 v i v_i vi?的物品。 此方法中,每次询问需要遍历数组 n n n次,单次询问时间复杂度是 O ( n 2 ) O(n^2) O(n2),总的时间复杂度达到了 O ( q n 2 ) O(qn^2) O(qn2),这个效率是远远达不到题目要求的。 下一步考虑优化: 显然在上述的过程中,价值差距不超过 k k k的相邻物品,我们遍历了很多次,如果我们能够避免这种冗余,效率会大大提高。 于是我们会想到预处理可行区段。对于一个区段 [ i , j ] [i,j] [i,j],满足对任意 p ∈ [ i , j ? 1 ] p\in[i,j-1] p∈[i,j?1],有 v p ? v p + 1 ≤ k v_p-v_{p+1}\le k vp??vp+1?≤k,那么这个区段中价值较低的物品都可以间接或直接地换成区段中价值较高的物品,根据贪心的思想,我们会选择区段中价值最大的那几个,其个数就等于原先在这个区段中属于你的物品数。使用前缀和可以 O ( 1 ) O(1) O(1)求出每个区段最终的价值之和。 这样,单次询问的时间复杂度下降到了 O ( n ) O(n) O(n),总的时间复杂度是 O ( q n + n log ? 2 n ) O(qn+n\log_2n) O(qn+nlog2?n),有所进步但是还是不够优秀。 继续考虑优化: 上述的方法中,每一次询问都需要处理可行区段,实际上很多的区段是相似乃至相同的,这又导致了冗余。 于是我们考虑离线询问。将询问按 k k k值大小从小到大排序,则我们在 k k k值变化时只需要进行区段的合并即可,而不必全部重新处理。考虑并查集,同时维护每个并查集中原本属于你的物品数,同样使用前缀和优化查询即可。 于是最终,总的时间复杂度可以下降到 O ( q + n log ? 2 n ) O(q+n\log_2n) O(q+nlog2?n),达到了题目要求。 这里只讲了总体思路,结合代码看更容易理解。 时间复杂度O ( q + n log ? 2 n ) O(q+n\log_2n) O(q+nlog2?n) AC代码
后记千呼万唤始出来,犹抱AK半遮面! 一次AK一次爽,一直AK一直爽 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 16:24:48- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |