题目链接:https://codeforces.ml/contest/1566/problem/D2
思路:按值从小到大、值相同的则序号由小到大进行排序。p数组即为a数组排好序后对应的下标(学到了新写法)。每一行里,值相同的再按序号从大到小重新排序,保证序号大的先进入里面的位置。最后统计每一行的正序对的数量。
ac代码:
// Problem: D2. Seating Arrangements (hard version)
// Contest: Codeforces - Codeforces Global Round 16
// URL: https://codeforces.com/contest/1566/problem/D2
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include <bits/stdc++.h>
using namespace std;
const int N = 9e4+4;
typedef long long LL;
int t;
int n,m;
int a[N],p[N];
int main(){
ios::sync_with_stdio(false);
cin >> t;
while(t--){
cin >> n >> m;
for(int i = 0;i < n * m;i++)cin >> a[i];
iota(p,p+n*m,0);
sort(p,p+n*m,[&](int i,int j){
if(a[i] != a[j])return a[i] < a[j];
return i < j;
});
int ans = 0;
for(int i = 0;i < n;i++){
for(int l = 0,r;l < m;l = r){
for(r = l;r < m&&a[p[i*m+l]] == a[p[i*m+r]];r++);
sort(p+i*m+l,p+i*m+r,greater<int>());
}
for(int j = 0;j < m;j++)
for(int k = j + 1;k < m;k++)
if(p[i*m+j] < p[i*m+k])ans++;
}
cout << ans << endl;
}
return 0;
}