求逆序数的方法

本文介绍了如何使用归并排序和树状数组的数据结构来计算整数数组中的逆序数。归并排序部分展示了递归过程以及如何减少数据交换,而树状数组则提供了前缀和功能,简化了求解过程。
摘要由CSDN通过智能技术生成

目录

1.归并排序求逆序数

2.树状数组求逆序数


1.归并排序求逆序数

int InversePairsCore(vector<int>& data, vector<int>& copy, int begin, int end) {
	if (begin == end)
		return 0;
	int mid = begin + (end - begin) / 2;
	int low1 = begin, high1 = mid, low2 = mid + 1, high2 = end;
	int left = InversePairsCore(copy, data, low1, high1);//这里的一步很绝啊,减少了数据交换的这一步
	int right = InversePairsCore(copy, data, low2, high2);

	long res = 0;
	int copyIndex = low1;
	// 归并排序:相当于两个有序数组合成一个有序表
	//下面就开始两两进行比较,若前面的数大于后面的数,就构成逆序对
	while (low1 <= high1 && low2 <= high2) {
		if (data[low1] < data[low2]) {
			
			copy[copyIndex++] = data[low1++];
		}
		else//data[low1] >= data[low2]
		{
			copy[copyIndex++] = data[low2++];
			res += high1 - low1 + 1;
			res %= 1000000007;
		}
			
	}

	while (low1 <= high1)
		copy[copyIndex++] = data[low1++];
	while (low2 <= high2)
		copy[copyIndex++] = data[low2++];


	return (left + right + res) % 1000000007;
}


int InversePairs(vector<int> data) {
	if (data.size() == 0)
		return 0;
	vector<int> copy(data);    // 辅助数组,每次递归后有序
	int res = InversePairsCore(data, copy, 0, data.size() - 1);
	
	//for (int a : data) {
	//	cout << a << " ";
	//}
	//cout << endl;

	//for (int a : copy) {
	//	cout << a << " ";
	//}
	//cout << endl;
	
	return res;

}

2.树状数组求逆序数

树状数组可以求前缀和

#include <iostream>
using namespace std;
#include <vector>




#define     lowbits(x)      ((x) & (-x))
const int MAX = 8;
vector<int> a(MAX + 1, 0);
vector<int> BITree(MAX + 1, 0);                      		//前缀和
void Update(int id, int new_data) {               		//维护数据
    int temp = id;
    int increse = new_data - a[id];                 		//获取修改结点的增量
    while (temp <= MAX) {
        BITree[temp] += increse;                  		//对每个父节点都要修改增量
        temp += lowbits(temp);                    		//向前反推父节点直到根节点停止
    }
}
int GetSum(int id) {                             		//前缀和
    int sum = 0;      int temp_id = id;
    while (temp_id > 0) {
        sum += BITree[temp_id];
        temp_id -= lowbits(temp_id);
    }
    return sum;
}
//int main(void) {
//    for (int i = 1; i <= MAX; i++)
//        Update(i, i);
//    printf("区间[2,6]的和:%d", GetSum(6) - GetSum(2 - 1));	//求SubArr=GetSum[j]-GetSum[i-1]
//    return 0;
//}

    int main(void) {
        int n;
        cin >> n;
        vector<int> v(n + 1, 0);
        for (int i = 1; i <= n; i++) {
            cin >> v[i];
            if (v[i] == 1)
                v[i] = -1;
            else
                v[i] = 1;
           // cout << v[i] << ' ';
        }
  


        //vector<int> a(MAX + 1, 0);
        //vector<int> BITree(n+1, 0);
        for (int i = 1; i <=n; i++)
            Update(i, v[i]);
        for (int i = 1; i <=n; i++)
            cout<<BITree[i]<<' ';
       //printf("区间[2,6]的和:%d", GetSum(6) - GetSum(2 - 1));	//求SubArr=GetSum[j]-GetSum[i-1]
        return 0;
    }


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值