题意:给N(1e5)个数的一个全排列,每次可以交换相邻的数,问最小交换次数达到数组满足a[i+1] = (a[i]%n)+1。
思路:假如换成1,2,3...n的排列,显然答案就是逆序数,那么加如1最终在位置2,留意到逆序数的变化与数字5的位置有关,因为数字5要最终去位置1了,所以枚举1的最终位置,过程O(1)维护逆序数。
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 1e5+30;
int n, id[maxn], sum[maxn];
void add(int x){
for(;x<=n;x+=x&-x) ++sum[x];
}
int query(int x){
int res = 0;
for(;x>0;x-=x&-x) res += sum[x];
return res;
}
int main(){
int T, x;
for(scanf("%d",&T);T;--T){
scanf("%d",&n);
for(int i=1; i<=n; ++i){
scanf("%d",&x);
id[x] = i;
sum[i] = 0;
}
LL tot = 0, ans;
for(int i=n; i>0; --i){
tot += query(id[i]);
add(id[i]);
}
ans = tot;
for(int i=n; i>1; --i){
tot -= n-id[i];
tot += id[i]-1;
ans = min(ans, tot);
}
printf("%lld\n",ans);
}
return 0;
}