Codeforces Educational Codeforces Round 164 E. Chain Reaction 【思维、分块、调和级数复杂度】

E. Chain Reaction

E

题意

n n n 个怪物排成一行,第 i i i 个怪物的生命值为 a i a_i ai
当一只怪物的生命值为正数时,它才被认为是活着

假设你的闪电技能每次能够造成 k k k 点伤害,你每次可以选择一个怪物攻击,这只怪物会先受到 k k k 点伤害,并且闪电会向两边传递,直到遇到一只已经死亡的怪物,或者左右端点

现在对于 ∀ k ∈ [ 1 , m a x ( a 1 , a 2 , . . . , a n ) ] \forall k \in [1, max(a_1,a_2,...,a_n)] k[1,max(a1,a2,...,an)],输出击败所有怪物的最小攻击次数

思路

我们先从 k = 1 k = 1 k=1 的特例入手,第一次攻击会传播至所有的怪物,我们一直攻击,直到有一只怪物死亡,那么从此刻开始,所有的怪物会被分成若干个互相隔离的子问题,因为闪电无法在不同的隔离快间传递了!
我们继续在其中一个块中操作,继续攻击直到又一只怪物死亡,这个块又被分割成子问题

那么我们可以得出结论:本题不存在最小攻击次数一说,不管如何选择操作对象,最终所需要的总攻击数都是一样

那么我们可以从 1 1 1 号怪物开始攻击,直到它死亡,需要 a 1 a_1 a1 次攻击( k = 1 k =1 k=1),那么我们继续移动到 2 2 2 号怪物,此时有两种情况:

  1. a 2 ≤ a 1 a_2 \leq a_1 a2a1,由于闪电的传递 2 2 2 号怪物早已死亡,无需操作
  2. a 2 > a 1 a_2 > a_1 a2>a1,需要额外操作 a 2 − a 1 a_2 - a_1 a2a1 次,补上伤害

后续也是类似情况,就像爬山峰一样,上山过程中才会贡献答案,下山过程不贡献答案

答案即为: a 1 + ∑ i = 2 n m a x ( 0 , a i − a i − 1 ) a_1 + \sum_{i = 2}^{n}max(0, a_i - a_{i - 1}) a1+i=2nmax(0,aiai1)

以上是 k = 1 k = 1 k=1 的分析,我们在 O ( n ) O(n) O(n) 下求出了答案

对于其他的 k ≥ 2 k \geq 2 k2,我们不妨将每个怪物的生命值改为: ⌈ a i k ⌉ \lceil \dfrac{a_i}{k} \rceil kai

也就是这个怪物需要上取整次攻击,答案变为: ⌈ a 1 k ⌉ + ∑ i = 2 n m a x ( 0 , ⌈ a i k ⌉ − ⌈ a i − 1 k ⌉ ) \lceil \frac{a_1}{k} \rceil + \sum_{i = 2}^{n}max(0,\lceil \frac{a_i}{k} \rceil - \lceil \frac{a_{i-1}}{k} \rceil) ka1+i=2nmax(0,kaikai1⌉)

我们提前将 a i a_i ai系数存储起来,当 i = 1 或 a i > a i − 1 i = 1 或 a_i > a_{i-1} i=1ai>ai1 时, a i a_i ai 的系数 + 1 +1 +1;当 a i < a i + 1 a_i < a_{i + 1} ai<ai+1 时, a i a_i ai 的系数 − 1 -1 1

最后我们只需要将每个 a i a_i ai 对应的系数乘上 ⌈ a i k ⌉ \lceil \frac{a_i}{k} \rceil kai 累加,就是答案

暴力扫描求解复杂度是: O ( k n ) O(kn) O(kn),显然不行,考虑优化:

有两种优化方法,一种是:数论分块,一种是利用调和级数复杂度

  1. 数论分块做法,时间复杂度: O ( n A ) O(n\sqrt A) O(nA )
    注意到对于当前的 k k k ⌈ a i k ⌉ \lceil \frac{a_i}{k} \rceil kai 的取值只有 O ( A ) O(\sqrt A) O(A ) 种( A A A a i a_i ai 最大值),这是因为:考虑 ∀ i ≤ A , A i ≥ i \forall i \leq \sqrt A,\frac{A}{i} \geq i iA iAi,也就是大概 2 A 2\sqrt A 2A 种取值,我们采用数论分块的做法即可
    具体就是,以 a n s i ans_i ansi 表示 k = i k=i k=i 的答案,那么对于每个 a i a_i ai,将它对 ⌈ a i k ⌉ \lceil \frac{a_i}{k} \rceil kai 的取值分割成 O ( a i ) O(\sqrt a_i) O(a i) 块,利用差分来区间统计块内的贡献
#include<bits/stdc++.h>
#define fore(i,l,r)	for(int i=(int)(l);i<(int)(r);++i)
#define fi first
#define se second
#define endl '\n'
#define ull unsigned long long
#define ALL(v) v.begin(), v.end()
#define Debug(x, ed) std::cerr << #x << " = " << x << ed;const int INF=0x3f3f3f3f;
const long long INFLL=1e18;typedef long long ll;int main(){std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout.tie(nullptr);int n;std::cin >> n;std::vector<int> a(n + 1, 0);fore(i, 1, n + 1) std::cin >> a[i];int mx = *max_element(ALL(a));std::vector<ll> ans(mx + 5, 0);fore(i, 1, n + 1){int coef = 0; //coef表示正负if(a[i] > a[i - 1]) ++coef;if(i + 1 <= n && a[i] < a[i + 1]) --coef;int r = a[i];ans[r + 1] += coef; //k大于ai的通通上取整取值为1while(r > 0){ll val = (a[i] + r - 1) / r; //val 表示ai对每个k上取整的系数int l = (a[i] + val - 1) / val; //l,r左右边界ans[l] += val * coef;ans[r + 1] -= val * coef;r = l - 1; //下一块}}fore(i, 1, mx + 1){ans[i] += ans[i - 1];std::cout << ans[i] << ' ';}return 0;
}

  1. 调和级数复杂度做法,时间复杂度: O ( n + A log ⁡ A ) O(n + A\log A) O(n+AlogA)
    还是同样的,我们先统计每个 a i a_i ai 的系数,

注意到:对于当前的 k k k,当 a i ∈ [ 1 , k ] a_i \in [1, k] ai[1,k] 时, ⌈ a i k ⌉ = 1 \lceil \frac{a_i}{k} \rceil = 1 kai=1
a i ∈ [ k + 1 , 2 k ] a_i \in [k + 1, 2k] ai[k+1,2k] 时, ⌈ a i k ⌉ = 2 \lceil \frac{a_i}{k} \rceil = 2 kai=2
a i ∈ [ 2 k + 1 , 3 k ] a_i \in [2k + 1, 3k] ai[2k+1,3k] 时, ⌈ a i k ⌉ = 3 \lceil \frac{a_i}{k} \rceil = 3 kai=3

那么我们可以将每个 a i a_i ai 对当前的 k k k 的贡献按照 ⌈ a i k ⌉ \lceil \frac{a_i}{k} \rceil kai,分成 k k k 块,

那么对于每个 k k k,我们要计算: O ( A 1 + A 2 + A 3 + . . . + A A ) = O ( A ⋅ ( 1 1 + 1 2 + . . . + 1 A ) ) = O ( A log ⁡ A ) O(\frac{A}{1} + \frac{A}{2} + \frac{A}{3} + ... + \frac{A}{A}) = O(A \cdot (\frac{1}{1} + \frac{1}{2} + ... + \frac{1}{A})) = O(A \log A) O(1A+2A+3A+...+AA)=O(A(11+21+...+A1))=O(AlogA)

只需要用前缀和数组预存一下每个 a i a_i ai 的系数,即可快速区间查询

#include<bits/stdc++.h>
#define fore(i,l,r)	for(int i=(int)(l);i<(int)(r);++i)
#define fi first
#define se second
#define endl '\n'
#define ull unsigned long long
#define ALL(v) v.begin(), v.end()
#define Debug(x, ed) std::cerr << #x << " = " << x << ed;const int INF=0x3f3f3f3f;
const long long INFLL=1e18;typedef long long ll;int main(){std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout.tie(nullptr);int n;std::cin >> n;std::vector<int> a(n + 1, 0);fore(i, 1, n + 1) std::cin >> a[i];int mx = *max_element(ALL(a));std::vector<ll> sum(mx + 5, 0); //前缀和fore(i, 1, n + 1){int coef = 0; //coef表示正负if(a[i] > a[i - 1]) ++coef;if(i + 1 <= n && a[i] < a[i + 1]) --coef;sum[a[i]] += coef;}fore(i, 2, mx + 1)	sum[i] += sum[i - 1];fore(k, 1, mx + 1){ll ans = 0;for(int l = 1; l <= mx; l += k){int r = std::min(mx, l + k - 1);ans += (l + k - 1) / k * (sum[r] - sum[l - 1]);}std::cout << ans << ' ';}return 0;
}

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

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

相关文章

如何使用 Vercel 托管静态网站

今天向大家介绍 Vercel 托管静态网站的几种方式&#xff0c;不熟悉 Vercel 的伙伴可以看一下之前的文章&#xff1a;Vercel: 开发者免费的网站托管平台 Github 部署 打开 Vercel 登录界面&#xff0c;推荐使用 GitHub账号 授权登录。 来到控制台界面&#xff0c;点击 Add New …

Linux——NFS网络文件系统

在生产环境中共享宿主目录可以用于集中管理账户 一、存储设备 DAS 是直连存储相当于移动硬盘 NAS 是网络文件系统&#xff0c;挂载后可以直接访问 SAN 存储区域网络 IPSAN 网线连接 共享的是设备&#xff0c;需要挂载后分区使用 FCSAN 光纤连接 二、服务的管理 1、安…

【一些神金】怎么缓解工作压力?使用VS-code彩虹屁插件

怎么缓解工作压力&#xff1f; 其实吃点好的&#xff0c;多睡一会儿&#xff0c;再锻炼锻炼身体就好。 但我只是想炫耀一下这个彩虹屁插件。 原版插件&#xff1a;VS-code-Rainbowfart 我的版本&#xff1a;RainbowFart-Oberon 基于 MIT 开源&#xff0c;包括所有设计资源及音…

影视后期特效合成:DaVinci Fusion Studio19 激活版

DaVinci Fusion Studio是一款功能强大的影视后期特效合成软件&#xff0c;可广泛应用于视觉效果、广播电视设计、动态图形设计、3D动画设计等领域。 如综合的绘图、动态掩蔽、遮片、图层叠加、字幕等工具&#xff0c;结合高效的粒子生成系统&#xff0c;通过它可以创建各种精细…

【电控笔记5.10】Luenberger估测器

Luenberger估测计 单积分器:pi控制器的补偿 双积分器:使用pid控制器的补偿 除了受控厂跟传感器,其他都在mcu 去掉Rs就是一个PLL锁相环 带宽比PLL更大

【Linux】gdb的简单使用

文章目录 一、gdb是什么&#xff1f;二、使用说明1. 安装2. 注意事项3. 常用调试指令3.1 gdb3.2 l3.3 r3.4 n3.5 s3.6 b3.7 info b3.8 finish3.9 p3.10 set var3.11 c3.12 d breakpoints3.13 d n3.14 disable/enable breakpoints3.15 disable/enable n3.16 info b3.17 display …

如何在Windows服务做性能测试(CPU、磁盘、内存)

目录 前言1. 基本知识2. 参数说明 前言 由于需要做一些接口测试&#xff0c;测试是否有真的优化 1. 基本知识 该基本知识主要用来用到Performance Monitor&#xff0c;以下着重介绍下这方面的知识 性能监视器&#xff08;Performance Monitor&#xff09;&#xff1a;Windo…

梯度下降法总是在同一点收敛吗?

梯度下降法总是在同一点收敛吗&#xff1f; 梯度下降法并不总是在同一点收敛。梯度下降法的收敛取决于多个因素&#xff0c;包括初始参数的选择、学习率的设置、损失函数的形状等。 以下是一些影响梯度下降法收敛行为的关键因素&#xff1a; 1.初始参数&#xff1a; 初始参数…

【数据库】三、数据库SQL语言命令(基础从入门到入土)

【全文两万多字&#xff0c;涵盖大部分常见情况&#xff0c;建议点赞收藏】 目录 文章目录 目录安装SQL语言1.使用2.DATABASE查看所有库新建数据库修改数据库删除数据库连接数据库 3.TABLE创建表查看库所有表删除表查看表信息重命名表修改表字段&#xff08;列&#xff09;表中…

【八股】Java基础、集合、JVM

面向对象三大特性 1 封装&#xff1a; 将 方法 和 属性 写到同一个类中&#xff0c;并将属性 私有化&#xff0c;生成 get set方法&#xff0c;外部访问属性需要通过get和set方法,内部可以直接访问属性&#xff0c;这样的一个类我们认为它完成了封装。 2 继承&#xff1a; 子…

月入8k,21岁计算机专业男孩转行网优,天赋可以让人发光,努力也能!

今天的主人公是一位仅21岁的年轻小帅哥&#xff0c;大学学的是计算机专业&#xff0c;毕业后的工作是卖苦力&#xff0c;工作一段时间后毅然决然的选择了转行后台网优&#xff0c;让我们一起来看看这位21岁男孩转行背后的故事... 卖苦力&#xff0c;是没有前途的 今天的主人公…

【c++】list类接口函数介绍与深度剖析模拟实现

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;本篇文章来到list有关部分&#xff0c;这一部分函数与前面的类似&#xff0c;我们简单讲解&#xff0c;重难点在模拟实现时的迭代器有关实现 目录 1.List介绍2.接…

富集分析不求人,零代码可视化GO/KEGG分析结果

01 爱基百客云平台小工具使用 首先&#xff0c;打开爱基百客官网&#xff1a;http://www.igenebook.com&#xff1b;点击菜单栏最右侧“云平台”按钮。 弹出云平台界面&#xff08;下图&#xff09;&#xff0c;输入账号、密码和验证码方可登录&#xff1b;进入云平台&#xf…

《Beginning C++20 From Novice to Professional》第二章Fundamental Types

本章将介绍C的基础数据类型&#xff0c;主要涉及下列方面&#xff1a; 变量的声明、初始化、赋值整数字面量浮点数如何计算变量类型转换字符相关auto关键字 Variables, Data, and Data Types 这里先给出变量的定义&#xff1a;有名字的一块内存&#xff0c;这个变量的类型决…

2024-04-23 linux 查看内存占用情况的命令free -h和cat /proc/meminfo

一、要查看 Linux 系统中的内存占用大小&#xff0c;可以使用 free 命令或者 top 命令。下面是这两个命令的简要说明&#xff1a; 使用 free 命令&#xff1a; free -h这将显示系统当前的内存使用情况&#xff0c;包括总内存、已用内存、空闲内存以及缓冲区和缓存的使用情况。…

想冲宇宙厂,直接挂了。。。

宇宙厂实际是字节&#xff0c;这个称呼是因为字节跳动主宰了宇宙内一切App&#xff0c;有点家大业大的意思。 今天分享一位字节春招凉经&#xff0c;问了一些数据库和Java八股&#xff0c;没出算法题&#xff0c;直接挂了&#xff0c;竟然最喜欢出算法题的字节&#xff0c;这次…

c++ - 空间申请和释放 new/delete

文章目录 一、c/c内存分布二、new/delete 的使用三、malloc/free 和 new/delete 的对比四、new/delete 的实现原理五、匹配问题 一、c/c内存分布 求下面各个变量的位置 // c/c内存分布int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar …

前端零代码开发实践:页面嵌套+逻辑连线0开发扩展组件,实现切换开关控制扇叶转动。能无代码封装扩展组件,有别于常规的web组态或低代码平台

前言&#xff1a; 官网:http://www.uiotos.net/ 什么是 UIOTOS&#xff1f; 这是一款拥有独创专利技术的前端零代码工具&#xff0c;专注于解决前端界面开发定制难题&#xff0c;原型即应用&#xff01;具有页面嵌套、属性继承、节点连线等全新特性&#xff0c;学习门槛低…

敷尔佳2023年报前瞻:“医美面膜第一股”的护城河及2024展望

查理芒格曾说&#xff1a;“要去鱼多的地方打渔”。历数长线牛股辈出的领域&#xff0c;消费行业无疑是大赢家。此中&#xff0c;美业又是消费行业最好的细分赛道之一。 4月26日&#xff0c;A股“医美面膜第一股”–敷尔佳(SZ:301371)将发布2023年财报&#xff0c;按惯例对本季…