#P2446. 逆序对.线段树.填空题

逆序对.线段树.填空题

题目描述

猫猫 TOM 和小老鼠 JERRY 最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。

最近,TOM 老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中 ai>aja_i>a_ji<ji<j 的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。注意序列中可能有重复数字。

输入格式

第一行,一个数 nn,表示序列中有 nn个数。

第二行 nn 个数,表示给定的序列。序列中每个数字不超过 10910^9

输出格式

输出序列中逆序对的数目。

样例

6
5 4 2 6 3 1
11

数据规模

对于 20%20\% 的数据,n100n \leq 100

对于 40%40\% 的数据,n5×103n \leq 5 \times 10^3

对于所有数据,n105n \leq 10^5

完成程序

下面的程序基于树状数组的算法。

#include<bits/stdc++.h>
using namespace std;

#define mid (tr[idx].left+tr[idx].right)/2
#define LC idx*2
#define RC idx*2+1

int n;
struct Node {
	int val, pos;
	bool operator < (const Node& a) const {
		return val < a.val||(val==a.val&&pos<a.pos);
	}
} a[100001];

struct TreeNode{
	int left,right,sum;
}tr[400001]; // 至少要 4 倍的 n

void create_tree(int idx,int l,int r){
	// 建树的时候,没有数据,所以 sum 为 0 ,不需要初始化
	tr[idx].left = l;
	tr[idx].right = r;
	if(__填空(1)__){
		create_tree(LC,l,mid);
		create_tree(__填空(2)__);
	}
}

void update(int idx,int x){ // 在 下标为 x 到地方加 1
	if(tr[idx].left > x || tr[idx].right < x) __填空(3)__;
	if(tr[idx].left==tr[idx].right && tr[idx].left==x) __填空(4)__;
	else{
		update(LC,x);
		update(RC,x);
		__填空(5)__;
	}
}

int query(int idx,int l, int r){ // 查询下标 [l,r] 的和
	if(tr[idx].left>r || tr[idx].right < l ) return 0;
	if(tr[idx].left>=l && tr[idx].right<=r) return tr[idx].sum;
	return __填空(6)__;
}

int main(){

	scanf("%d", &n);
	create_tree(1,1,n); // 初始化线段树

	for (int i =1; i <=n; i++){
		scanf("%d", &a[i].val);
		a[i].pos = i;
	}
	sort(a+1, a+n+1);
	// 排序之后,完成离散化,a[i].pos 记录了第 i 小的数原来的位置。

	long long ans = 0;
	// 从小到大把数字加入到树状数组(加入的时候,是按照原来的位置去加 1)
	for (int i = 1; i <= n; i++){
		// 加到第 i 小的数字的时候,第 1 小到第 i-1 小的数已经在树状数组中,有一部分在 a[i].pos 前面,有一部分在 a[i].pos 后面
		// 第 i 小的数可以和 a[i].pos 位置后面的数(比 a[i].val 小的哪些)组成逆序对
		ans += query(__填空(7)__);
		update(__填空(8)__);
	}

	printf("%lld", ans);
}

填空(1): {{ input(1) }}

填空(2): {{ input(2) }}

填空(3): {{ input(3) }}

填空(4): {{ input(4) }}

填空(5): {{ input(5) }}

填空(6): {{ input(6) }}

填空(7): {{ input(7) }}

填空(8): {{ input(8) }}