[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\)】和【出现次数】,意会一下。