题意:
给你一个无限大的整数序列 p = {1, 2, 3, ...};
有 n 次操作,每次操作交换第 ai 个数和第 aj 个数;
求序列中逆序对的个数;
题解:
考虑交换完后的序列,存在连续的区间 [ i , j ] 使得 p[ i ] = i , 那么分下一下这种区间的特点
假设 i 之前有 x 个数大于 p[ i ],那么可知对于第 i 个数有 x 个逆序对,同理,因为 p[ i+1 ] = p[ i ]
所以 i+1 之前也一定有且只有 x 个数大于 p[ i+1 ],那么第 i+1 个数也有 x 个逆序对,那么对于连续的区间[i,j]
易的区间 [ i , j ] 与其之前的数可构成的逆序对的个数为 (j-i+1)*x 个,那么可将其映射为一个值 i ,并记录其有 (j-i+1) 个数;
例如,假设 n 次操作为
1 4
1 8
那么交换完后,前 8 个数的排列状况为:
1 2 3 4 5 6 7 8
8 2 3 1 5 6 7 4
那么可得区间 [2,3] 和区间[5,6]的值未发生改变,当然区间[9,+∞]也为发生改变,但[9,+∞]并不影响答案,所以不用考虑。
那么根据之前提到的,将为改变的大区间映射到某个值身上,并记录有多少数映射到这个值上了,如下所示:
1 2 3 4 5
8 2 1 5 4
映射完后,区间[2,3]合并到了2上,区间[5,7]合并到了5上,接下来就是求映射完后的数组的逆序对总个数,这就变成了经典的
树状数组求逆序对个数的题了。
这就完事了么????当然不是~~~
考虑 4 这个值,其之前的 5 只给 4 提供了一个逆序对,但实际上 6,7 也会提供,那么这就少算了两个逆序对数,这该怎么办呢?
考虑某个区间 [i , j],一共有 j-i+1 个数,易得区间 [ i , j ] 只会影响其之后且值小于 i 的数,那么就再用一次树状数组,如果来到了某个
映射的值,那么将 i 之后的数通过树状数组 +(j-i),对于某个在其之后且值小于 i 的数 x ,直接在答案上额外加上 Sum(x+1)即可。
AC代码:
1 #include 2 #include 3 #include 4 #include
View Code