cf1540d-solution

CF1540D Solution

link

题意:

给你一个长度为 n 的序列 a,支持以下操作:

1 x y:令 axy

2 x:构造 1n 的排列 p,满足 i[1,n]p1pi1 恰有 ai 个数大于 pi。求 px


为方便,将 aiiai,这样 ai 就是 p1pipi 的排名。

手玩一下构造。假设有 a={1,2,2,1,3},从 15 逐个构造 pi

a : 1 2 2 1 3
p : 1
p : 1 2
p : 1 3 2
p : 2 4 3 1
p : 2 5 4 1 3

你发现每次构造 pi 时就是将 piai,将前面所有 aip 全部 +1

这里有重要性质:每次构造只会影响前面已构造的 p,不会影响到后面还没构造的 p

回到原题,题目每次要求 px,那么根据上面的性质,我们直接从 px 开始构造,并计算构造后面 p 时对 px 的影响。

那么询问转化为,初始 ans=px,然后从 x+1 枚举到 n,如果 ansaiansans+1

考虑序列分块,块长为 B。我们尝试在每块内维护 nxtx 表示数 x 从块左端点走到右端点会增加多少。

那么由于块长为 Bnxt 的值全部都 B 且单调不降。

nxt 可以被看做一个只有 B 种取值的分段函数,函数值分别为 1,2,3,,B

我们直接维护块内的分段函数的 B 个自变量边界,询问暴力跳块用 upper_bound 询问函数值即可。

最后处理单点修改。考虑每块开线段树,线段树结点维护它对应区间的分段函数边界,push_up 直接线性归并即可。

这样单点修改复杂度是 iB2i=O(B) 的。

复杂度是 O(n(B+nBlogn)) 的,取 B=nlogn,最终时间 O(nnlogn),空间 O(nlogn)

听说可以分散层叠 O(nn)(?


upd:好像不用分散层叠也可以 O(nn)

具体地,把询问和修改塞到每个块中,离线从左到右逐块处理,

每个块的修改操作将询问分成若干段,每段内线段树根节点的形态是一样的。于是可以双指针直接扫。

注意双指针之前要把同一段中的询问按照它本来的 ans 排序,这个排序用快排复杂度会退化,用计数排序即可。

还有为了做到线性空间,我们在塞询问时只把询问塞到最左边的块,然后处理完这个块把询问塞到下一个块中。

时间复杂度是 O(nn),空间 O(n)。然而常数过大被带 log 的吊着踩。

posted @   iorit  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示