[NOI Online #1 提高组]冒泡排序 题解

思维题。需要弄清

  • 冒泡排序的本质
  • 每一轮冒泡排序对逆序对的影响

冒泡排序的本质是将一个数放到他的“后面第一个大于”之前,并把它俩之间的数向左平移一位。
这个数能够向右征服的充要条件是左边没有比它大的数。原因是,一旦有,他就成了被征服的,手无缚鸡之力。
因此,每一轮冒泡排序会使每一个数值上的逆序对 \(-1\)(如果小于 0 了就再和 0 取 max)。原因是,一个数要么被征服,要么征服别人,被征服的,它左边就少了一个大于它的数,征服别人的,原来的逆序对数就是 0,不妨碍 -1 再取 max。
因此,第 \(k\) 轮冒泡排序结束后的总逆序对数就是

\[\sum_{1\le i \le n,b_i>k}(b_i-k) \]

\(b_k\) 是数值 \(k\) 上的逆序对数。
显然可以用值域树状数组维护。
修改和询问就显得很简单了,只需要在 \(c\) 上查询即可。
另外,代码实现方面,需要三个树状数组 \(c,c_1,c_2\)\(c\) 是最开始算逆序对的,\(c_1,c_2\) 分别用于记录 \(b\) 的值域上的【出现次数\(\times b\)】和【出现次数】,意会一下。

posted @ 2021-10-23 10:56  pengyule  阅读(10)  评论(0编辑  收藏  举报