题意
有一个长度为 n n n的排列 p p p,你可以对它进行若干次把相邻两个数交换的操作,使得操作数 + ( i ! = p [ i ] ) +(i!=p[i]) +(i!=p[i])的 i i i的个数之和最小。
题解
考场思路:
剩下不到一小时开始想,注意到相同的操作不会重复进行,(容易证明)。于是交换操作是有用的,当且仅当能把完全乱序的包含
l
,
.
.
.
,
r
l,...,r
l,...,r区间[l,r]通过r-l次操作变为
l
,
.
.
.
,
r
l,...,r
l,...,r。一段区间能换的条件是什么呢?直观地想,
l
l
l这个数一定要换到位置
l
l
l,之后不知道为什么想假了,也没时间对拍,于是只拿到了20的暴力。
正解:
题解做法好像会复杂一点,自己想(自闭)了半天,发现题目有很强的性质,利用它就可以得到一个很简单的做法。
先考虑一段区间能换的条件:继续直观地想下去,
l
+
1
l+1
l+1这个数要换到
l
+
1
l+1
l+1,以此类推,条件就是区间逆序对对数等于
r
−
l
r-l
r−l。
于是问题变为找到尽量多的互不相交区间
[
l
,
r
]
[l,r]
[l,r],满足:
1.
a
[
i
]
!
=
i
(
l
≤
i
≤
r
)
a[i]!=i(l\le i\le r)
a[i]!=i(l≤i≤r)
2.
[
l
,
r
]
[l,r]
[l,r]内的数都出现一次
3.逆序对数
=
r
−
l
=r-l
=r−l
条件2相当于区间
m
a
x
=
l
,
m
i
n
=
r
max=l,min=r
max=l,min=r,看起来比较好考虑,先从它下手:
发现互不相交是一个比较麻烦的问题,但注意到对于两个有交集的合法区间,只可能取它们的交集(满足条件2且更可能满足条件1,3,且可以使答案尽量大)。于是只需对每一个右端点维护最后一个满足条件2的左端点(容易用单调栈维护),从最前面开始取,后面的区间若被前面覆盖到,舍去即可。
问题剩下给定一个区间,判断是否满足条件
1
,
3
1,3
1,3,由于区间的总长不超过
n
n
n,直接扫一遍即可,复杂度
O
(
n
l
o
g
n
)
O(nlogn)
O(nlogn),瓶颈在于求逆序对个数。