CF2006D Iris and Adjacent Products

题意

https://codeforces.com/contest/2006/problem/D

分析

考虑如果没有修改怎么重排最优。先把最大值丢进序列,再把最小值丢进序列,再把次大值丢进序列,再把次小值压进去,以此类推。感性理解的话不难发现这是最优情况,具体证明可以考虑调整法(但我懒)。

ba 排序后的结果,那么 maxaiai+1=maxbibni+1,简而言之就是 k 大值乘 k 小值的乘积最大值。如果 n 为奇数那么最中间的那个数没用。

如果要修改的话,显然要把当前最大值修改为 1,然后就变成了 k+2 大值和 k 小值的乘积最大值。

那么一个三方暴力就呼之欲出了:若一个 p 大值和一个 q 小值(满足 pq)的乘积大于 k,那么修改次数就需要至少为 pq2+1,最终答案就是对所有的 pq2+1 取 max。注意这里不需要讨论 pq 是奇数的情况,因为此时乘积大于 k 那么 pp+1 后乘积更大且修改次数不变。

当然这个暴力很容易优化成平方 log,但对正解没啥启发作用。

发现 k 很小,结合乘法运算的性质,考虑根号分治,把 k 的数分为一类(称之为第一类),>k 的数分为一类(称之为第二类)。显然两个第二类的数相乘必定大于 k,两个第一类的数相乘必定不大于 k。发现对于第二类数,我们不关心每个数的具体数值,只关系它跟哪些数相乘会大于 k。考虑把第二类的数重标号,将 x 重标号为 k+kx,表示这个数在和第一类数中大于 kx 的数相乘会大于 k,加上 k 只是为了区分第一类数。不难发现此时不同的数种类只有 2k 个。

考虑询问。由于不同的数种类只有 2k 个,所以我们完全可以把区间内每种数的出现次数存下来,跑一遍前缀和就可以知道值域在某段区间内的数的个数。

分类讨论:

  • 两个二类数相乘(前提是需要有至少两个二类数):把排名最小的二类数和排名最大的二类数相乘,能让修改次数卡满。
  • 一类数和二类数相乘:枚举每个二类数 x,求出排名最大的 x 以及所有 >xk 的数中排名最小的 y,能让修改次数卡满。

但是,如果维护出 sc,i 表示前缀 ic 的出现次数的话是 O(nk) 的,空间开不下。一种容易想到的方法是考虑莫队维护每种数的出现次数,时间复杂度 O(nn+qk),空间复杂度 O(n+q+k),可以通过。

代码:https://codeforces.com/contest/2006/submission/278952523

作者:dcytrl

出处:https://www.cnblogs.com/dcytrl/p/18404878

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   dcytrl  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
more_horiz
keyboard_arrow_up light_mode palette
选择主题
点击右上角即可分享
微信分享提示