ZOJ Monthly, June 2018 - J Good Permutation

本文介绍了一种通过计算特殊逆序对次数的方法来解决特定数列排序问题的算法实现。该算法利用了树状数组(Binary Indexed Tree)进行优化,通过预处理和动态更新的方式高效地计算出将数列转换为特定排列所需的最小交换次数。
点击打开链接

题意:

给你一个数列。

问你交换成特殊逆序对所需要的次数。


特殊逆序对:1 2 3 4 5、5 1 2 3 4、4 5 1 2 3、3 4 5 1 2 ……


POINT:

先算出1 2 3 4 5 正常的逆序对所需要的次数。

然后for循环更新。


#include <iostream>
#include <stdio.h>
using namespace std;
const int N = 1e5+55;
#define LL long long
int pos[N];
int num[N];
int n;

void add(int x,int p)
{
	for(int i=x;i<=n;i+=i&-i)
		num[i]+=p;
}

int sum(int x)
{
	int ans=0;
	for(int i=x;i>=1;i-=i&-i)
		ans+=num[i];
	return ans;
}


int main()
{
	int T;
	while(~scanf("%d",&T)){
		while(T--){
			scanf("%d",&n);
			for(int i=1;i<=n;i++){
				int x;
				scanf("%d",&x);
				pos[x]=i;
				add(i,1);
			}
			LL ans=0;
			for(int i=1;i<=n;i++){
				add(pos[i],-1);
				ans+=(LL)sum(pos[i]);
			}
			LL now = ans;
			for(int i=1;i<n;i++){
				now=now-(pos[i]-1)+n-pos[i];
				ans=min(ans,now);
			}
			printf("%lld\n",ans);


		}
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值