题解:[ABC396F] Rotated Inversions

本文遵循 CC BY-NC-ND 4.0 协议,作者:U•ェ•*U,转载请获得作者授权。

先求 k = 0 k=0 k=0 时的逆序数:用树状数组在 O ( N log ⁡ M ) O(N\log M) O(NlogM) 时间内统计标准逆序数。

分析 k → k + 1 k\to k+1 kk+1 时逆序数的变化: 观察每个位置 i i i ,当 k k k 增加 1 1 1 时, B i = ( A i + k ) m o d    M B_i = (A_i+k)\mod M Bi=(Ai+k)modM 只有在等于模数(即 A i + k = M − 1 A_i+k = M-1 Ai+k=M1)时变为 0 0 0,就改变了它在序列中的相对大小。可以证明,当某个位置 i i i 满足 k = M − 1 − A i k = M-1-A_i k=M1Ai 时,该位置会改变贡献,对全局逆序数的影响为
( 在该位置前的个数 ) − ( 在该位置后的个数 ) = 2 ⋅ i − ( N − 1 ) ( \text{在该位置前的个数} ) - ( \text{在该位置后的个数} ) = 2\cdot i - (N-1) (在该位置前的个数)(在该位置后的个数)=2i(N1)
因此可以令一个差分数组 d i f f diff diff(下标范围 [ 0 , M − 1 ] [0,M-1] [0,M1])满足:对于每个位置 i i i,在 k = M − 1 − A i k = M-1-A_i k=M1Ai 时,加上 $2\cdot i-(N-1) $。

最后,对于每个 k k k,我们加上 d i f f k diff_k diffk 即可。

import sys

n, m = map(int, sys.stdin.readline().split())
a = list(map(int, sys.stdin.readline().split()))
tree = [0] * (200010)
diff = [0] * (200010)

def add(x, val):
    x += 1
    while x <= m:
        tree[x] += val
        x += (x & -x)

def query(x):
    x += 1
    res = 0
    while x:
        res += tree[x]
        x -= (x & -x)
    return res

def main():
    tmp = 0
    for i in range(n):
        tmp += i - query(a[i])
        add(a[i], 1)
        diff[m - 1 - a[i]] += (2 * i - (n - 1))

    print(tmp)
    for k in range(1, m):
        tmp += diff[k - 1]
        print(tmp)

if __name__ == '__main__':
    main()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值