You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

57 lines
1.8 KiB

2 years ago
#include <bits/stdc++.h>
using namespace std;
const int N = 500010;
typedef long long LL;
LL ans;
int n;
//每个输入的数字我们关心两个方面1、数值 2、位置(序号)
struct Node {
int val;
int id;
} d[N];
bool operator<(const Node &a, const Node &b) {
if (a.val == b.val) return a.id > b.id; //两个数一样大,序号大的靠前,这样统计出来的正序对才正确
return a.val > b.val; //数不一样大,数大的靠前
}
//下面是树状数组模板
int t[N];
//返回非负整数x在二进制表示下最低位1及其后面的0构成的数值
int lowbit(int x) {
return x & -x;
}
//将序列中第x个数加上k
void add(int x, int k) {
for (int i = x; i <= n; i += lowbit(i)) t[i] += k;
}
//查询序列前x个数的和
int sum(int x) {
int sum = 0;
for (int i = x; i; i -= lowbit(i)) sum += t[i];
return sum;
}
int main() {
scanf("%d", &n);
//读入每个数分别将数值、序号记录到结构体数组d中
for (int i = 1; i <= n; i++) {
scanf("%d", &d[i].val);
d[i].id = i;
}
//对结构体数组进行排序,大的在前,小的在后;如果数值一样,序号大的在前,小的在后
sort(d + 1, d + 1 + n);
//逆序对的定义i<j && d[i]>d[j]
// d数组是由大到小排完序的按由大到小的顺序动态维护树状数组计算每次变化后出现的i<j 的个数。
for (int i = 1; i <= n; i++) {
//将d[i].id放入树状数组描述这个号的数字增加了1个
add(d[i].id, 1);
//查询并累加所有比当前节点id小的数字个数
ans += sum(d[i].id - 1);
}
//输出结果
cout << ans << endl;
return 0;
}