题意
https://codeforces.com/contest/2006/problem/D
分析
考虑如果没有修改怎么重排最优。先把最大值丢进序列,再把最小值丢进序列,再把次大值丢进序列,再把次小值压进去,以此类推。感性理解的话不难发现这是最优情况,具体证明可以考虑调整法(但我懒)。
令 为 排序后的结果,那么 ,简而言之就是 大值乘 小值的乘积最大值。如果 为奇数那么最中间的那个数没用。
如果要修改的话,显然要把当前最大值修改为 ,然后就变成了 大值和 小值的乘积最大值。
那么一个三方暴力就呼之欲出了:若一个 大值和一个 小值(满足 )的乘积大于 ,那么修改次数就需要至少为 ,最终答案就是对所有的 取 max。注意这里不需要讨论 是奇数的情况,因为此时乘积大于 那么 后乘积更大且修改次数不变。
当然这个暴力很容易优化成平方 log,但对正解没啥启发作用。
发现 很小,结合乘法运算的性质,考虑根号分治,把 的数分为一类(称之为第一类), 的数分为一类(称之为第二类)。显然两个第二类的数相乘必定大于 ,两个第一类的数相乘必定不大于 。发现对于第二类数,我们不关心每个数的具体数值,只关系它跟哪些数相乘会大于 。考虑把第二类的数重标号,将 重标号为 ,表示这个数在和第一类数中大于 的数相乘会大于 ,加上 只是为了区分第一类数。不难发现此时不同的数种类只有 个。
考虑询问。由于不同的数种类只有 个,所以我们完全可以把区间内每种数的出现次数存下来,跑一遍前缀和就可以知道值域在某段区间内的数的个数。
分类讨论:
- 两个二类数相乘(前提是需要有至少两个二类数):把排名最小的二类数和排名最大的二类数相乘,能让修改次数卡满。
- 一类数和二类数相乘:枚举每个二类数 ,求出排名最大的 以及所有 的数中排名最小的 ,能让修改次数卡满。
但是,如果维护出 表示前缀 中 的出现次数的话是 的,空间开不下。一种容易想到的方法是考虑莫队维护每种数的出现次数,时间复杂度 ,空间复杂度 ,可以通过。
代码:https://codeforces.com/contest/2006/submission/278952523
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!