【树状数组(逆序数)】hdu 3743 Frosh Week

本文详细介绍了如何通过离散化和线段树技术解决逆序数问题,提供了清晰的算法实现和实例分析。

http://acm.hdu.edu.cn/showproblem.php?pid=3743

分析:就是求逆序数,要注意离散化处理,题目信息也不说行清楚


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int NM=1000005;
int a[NM],c[NM];

struct Node{
	int vau,pos;
}node[NM];

int lowbit(int x)
{
	return x&(-x);
}

void add(int x)
{
	while(x<NM)
	{
		c[x]++;
		x+=lowbit(x);
	}
}

__int64 getsum(int x)
{
	__int64 ans=0;
	while(x>0)
	{
		ans+=c[x];
		x-=lowbit(x);
	}
	return ans;
}

bool comp(struct Node A,struct Node B)
{
	if(A.vau<B.vau) return 1;
	else return 0;
}

int main()
{
	int n,i;
	__int64 res;
	while(scanf("%d",&n)!=EOF)
	{
		memset(c,0,sizeof(c));
		for(i=1;i<=n;i++)
		{
			scanf("%d",&node[i].vau);
			node[i].pos=i;
		}
		sort(node+1,node+1+n,comp);
		for(i=1;i<=n;i++)
			a[node[i].pos]=i;

		res=0;
		for(i=1;i<=n;i++)
		{
			add(a[i]);
			res+=i-getsum(a[i]);	
		}
		printf("%I64d\n",res);
	}
	return 0;
}


### 统计数组中的逆序对数量 在数组中,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。统计数组中的逆序对数量可以通过归并排序的思想来实现。这种方法的时间复杂度为 $O(n \log n)$,比暴力法的 $O(n^2)$ 更加高效。 #### 实现思路 1. **分治策略**:将数组分成左右两个子数组,分别计算左半部分和右半部分的逆序对数量。 2. **合并阶段**:在归并排序的过程中,统计两个相邻子数组之间的逆序对数量。 3. **递归处理**:通过递归的方式,将问题分解为更小的子问题,最终合并得到整个数组的逆序对总数。 #### Python 代码示例 以下是一个基于归并排序思想的 Python 实现: ```python class Solution: def __init__(self): self.count = 0 def merge_sort(self, arr): if len(arr) <= 1: return arr mid = len(arr) // 2 left = self.merge_sort(arr[:mid]) right = self.merge_sort(arr[mid:]) return self.merge(left, right) def merge(self, left, right): merged = [] i = j = 0 while i < len(left) and j < len(right): if left[i] <= right[j]: merged.append(left[i]) i += 1 else: merged.append(right[j]) j += 1 self.count += len(left) - i merged.extend(left[i:]) merged.extend(right[j:]) return merged def inverse_pairs(self, nums): self.merge_sort(nums) return self.count % 1000000007 ``` #### 使用说明 - 初始化 `Solution` 类后,调用 `inverse_pairs` 方法即可得到数组中逆序对的数量。 - 最终结果会对 $1000000007$ 取模,以满足题目要求。 #### 示例 假设输入数组为 `[7, 5, 6, 4]`,调用代码后输出的结果为 `5`,因为该数组中有 5 个逆序对:`(7, 5)`、`(7, 6)`、`(7, 4)`、`(5, 4)` 和 `(6, 4)`。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值