#include<bits/stdc++.h>#definepbpush_backusingnamespace std;typedeflonglong LL;constint N =2e5+10;int n, m;
LL tr[N];//tr[i]表示当前数组元素中值 <= i的有多少intlowbit(int x){return x &-x;}voidadd(int x,int c){for(int i = x; i <= m; i +=lowbit(i)){
tr[i]+= c;}}
LL sum(int x){
LL res =0;for(int i = x; i >0; i -=lowbit(i)){
res += tr[i];}return res;}intmain(){
cin >> n >> m;
vector<int>a(n);for(int i =0; i < n; i ++){
cin >> a[i];}//存储每个值在原数组中的位置
vector<vector<int>>g(m);for(int i =0; i < n; i ++){
g[a[i]].pb(i);}
LL ans =0;//利用树状数组进行数组初始时的逆序数(即k = 0时)//把值x存储到位置x + 1//那么对于当前位置为i的值a[i],其位置在之前并比其值大的数组元素有sum(m) - sum(a[i] + 1)//然后在把当前的值的个数增加存入到树状数组中, 即add(a[i] + 1, 1)for(auto x : a){// x = a[i]
ans +=sum(m)-sum(x +1);add(x +1,1);}
cout << ans <<'\n';for(int c =1; c < m;++c){
LL c1 =0, c2 =0;for(int idx =0; idx < g[m - c].size(); idx ++){//如果x + c = m,在这一轮中x的值将会变为(x + c) % m = 0,逆序数就可能会发生变化//分别讨论增加与减少的数量,其值分别为c1、c2//在某个变为0的数之前有多少不为0的数呢?值为g[m - c][idx] - idx(减去了跟它同组变为0且在它前面的数)
c1 += g[m - c][idx]- idx;//同理需要计算,某个变为0的数之后有多少不为0的数。值为(n - 1) - g[m - c][idx] - (g[m - c].size() - 1 - idx)
c2 += n -1- g[m - c][idx]-(g[m - c].size()-1- idx);}
ans += c1 - c2;
cout << ans <<'\n';}return0;}
解法二、归并排序求逆序对
#include<bits/stdc++.h>#definepbpush_backusingnamespace std;typedeflonglong LL;constint N =2e5+10;int n, m;
LL tr[N];//tr[i]表示当前数组元素中值 <= i的有多少intlowbit(int x){return x &-x;}voidadd(int x,int c){for(int i = x; i <= m; i +=lowbit(i)){
tr[i]+= c;}}
LL sum(int x){
LL res =0;for(int i = x; i >0; i -=lowbit(i)){
res += tr[i];}return res;}//求解数组arr的逆序数
LL merge(vector<int>& arr,int left,int right){if(left >= right){return0;}int mid =(left + right)>>1;
LL res =merge(arr, left, mid)+merge(arr, mid +1, right);
vector<int>temp(right - left +1);int i = left, j = mid +1, k =0;while(i <= mid && j <= right){if(arr[i]<= arr[j]){
temp[k ++]= arr[i ++];}else{
res += mid - i +1;
temp[k ++]= arr[j ++];}}while(i <= mid) temp[k ++]= arr[i ++];while(j <= right) temp[k ++]= arr[j ++];for(int p =0; p < k; p ++){
arr[left + p]= temp[p];}return res;}intmain(){
cin >> n >> m;
vector<int>a(n);for(int i =0; i < n; i ++){
cin >> a[i];}//存储每个值在原数组中的位置
vector<vector<int>>g(m);for(int i =0; i < n; i ++){
g[a[i]].pb(i);}
LL ans =merge(a,0, n -1);
cout << ans <<'\n';for(int c =1; c < m;++c){
LL c1 =0, c2 =0;for(int idx =0; idx < g[m - c].size(); idx ++){//如果x + c = m,在这一轮中x的值将会变为(x + c) % m = 0,逆序数就可能会发生变化//分别讨论增加与减少的数量,其值分别为c1、c2//在某个变为0的数之前有多少不为0的数呢?值为g[m - c][idx] - idx(减去了跟它同组变为0且在它前面的数)
c1 += g[m - c][idx]- idx;//同理需要计算,某个变为0的数之后有多少不为0的数。值为(n - 1) - g[m - c][idx] - (g[m - c].size() - 1 - idx)
c2 += n -1- g[m - c][idx]-(g[m - c].size()-1- idx);}
ans += c1 - c2;
cout << ans <<'\n';}return0;}