【luogu P8376】排列(构造)(思维)
排列
题目链接:luogu P8376
题目大意
给你一个 k,要你构造一个长度不超过 90 的排列,使得这个排列的递增子序列个数恰好为 k。
思路
首先我们考虑构造出它至少要能到它的大小,那怎么增大的最快呢?
就直接按顺序,然后每次是 。
那你会发现你可以依此得到一个 ( 是 的最高位),不过要再加一个 。
(不过你会发现因为空串也算,但是你没有算上,所以不用加)
然后你会发现后面就是可以类似二进制拆分的搞,从而得到 。
接着就卡住了。。。
当然有一些神奇的随机化做法可以弄过去,但这里说一个从一个大佬的题解中看到的优美做法。
你观察为什么会卡,因为你是 的次数,而 ,答案是 ,它是 的一点五倍!
这启发我们用一些方法来优化常数。
自然前面的那 个无法优化,那我们考虑把后面的 减少一半。
怎么减少一半呢?你会发现如果你前面凑了两个位置,你可以通过一种方法使得后面两个连续的 只需要放一次!
如图,这两个的个数其实是一样的,因为你第二个图右边的那个点除了跟后面上面的黑点正常贡献,它可以有三种(自己,前面带上第一个红点,前面带上第二个红点)
那就是乘 ,亦或者说是给自己的前面加了一个 !
先看看这样能优化的个数,前面 占了两个,如果那后面如果不是连续的 ,那说明这个位置 只占了一半,可以正常弄,如果两个 我们就压缩到 个,优化了一半。
所以是刚好优化了一半的!
那我们就可以用这种方法来搞,然后接下来讲讲具体的:
那我们先从高位往低位跑一次,得到那些位置值正常弄,那些位置压缩弄。
然后我们接着考虑怎么排位置,就根据上面的第二张图来看:
首先黑色点都是大于红色点,直接把最大的排上去。
接着我们考虑怎么搞,因为我们要保证每个合并点前面要恰好有两个比它小的,这从高位往低位不再好搞,我们考虑从低位往高位搞。
然后因为你从低位往高位搞,构造出来是从右往左的,所以你要把你构造出来的序列最后翻转一下。
那继续想怎么弄,你考虑数是越来越大的,然后如果你要弄新合并点,你就预先留出两个位置给非合并点放,这两个位置是小的。
如果合并点后面又是合并点,那其实没有必要再弄,继续用哪个非合并点,然后大小比前面的非合并点大(因为你从后往前)即可。
那我们可以这样实现,我们一直给新合并点找两个位置,如果有普通点来了就占一个位置,新的位置再找。
然后如果来了合并点我们已经找好了,就不用再找,直接用下一个位置。
然后我们记录就弄两个指针指着普通点当前放在哪里,合并点当前放在哪里。
然后搞就可以啦,如果还是不知道可以看看代码的实现。
代码
__EOF__

本文链接:https://www.cnblogs.com/Sakura-TJH/p/luogu_P8376.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!