洛谷 P1908 逆序对
题目链接:
https://www.luogu.com.cn/problem/P1908
题目大意:
给长为 n 的序列,求序列中逆序对的数目
思路:
一、
归并:
#include
using namespace std;
#define LL long long
const int N = 5e5 + 10;
LL a[N], tmp[N], n, ans = 0;
void mergeSort(LL l, LL r){
if (l >= r) return;
LL mid = (l + r) >> 1, i = l, j = mid + 1, cnt = 0;
mergeSort(l, mid);
mergeSort(mid + 1, r);
while (i <= mid || j <= r)
if (j > r || (i <= mid && a[i] <= a[j]))
tmp[cnt++] = a[i++];
else
tmp[cnt++] = a[j++], ans += mid - i + 1;
for (LL k = 0; k < r - l + 1; k++)
a[l + k] = tmp[k];
}
int main(){
cin >> n;
for (int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
mergeSort(1, n);
cout << ans << "\n";
return 0;
}
二、
树状数组:
#include
using namespace std;
#define LL long long
const int N = 5e5 + 10;
LL ans;
int n, tree[N], p[N];
struct node{
int num, index;
}nd[N];
bool cmp(node a, node b){
if (a.num == b.num) return a.index < b.index;
return a.num < b.num;
}
int lowbit(int k){
return k & -k;
}
void update(int x, int k){
while (x <= n){
tree[x] += k;
x += lowbit(x);
}
}
int query(int x){
int t = 0;
while (x != 0){
t += tree[x];
x -= lowbit(x);
}
return t;
}
void solve(){
cin >> n;
for (int i = 1; i <= n; i++){
scanf("%d", &nd[i].num);
nd[i].index = i;
}
sort(nd + 1, nd + n + 1, cmp);
for (int i = 1; i <= n; i++)
p[nd[i].index] = i;
for (int i = 1; i <= n; i++){
update(p[i], 1);
ans += (i - query(p[i]));
}
cout << ans << "\n";
}
int main(){
solve();
return 0;
}