这是该问题的困难版本。唯一的区别是,在这个版本中,1≤n≤300。
电影院的座位可以表示为有n行和m列的表格。每行的座位都用1到n的整数编号,从左到右连续编号:在第k行,从m(k-1)+1到mk,所有行1≤k≤n。
1 2 ⋯ m-1 m
m+1 m+2 ⋯ 2m-1 2m
2m+1 2m+2 ⋯ 3m-1 3m
⋮ ⋮ ⋱ ⋮ ⋮
m(n-1)+1 m(n-1)+2 ⋯ nm-1 nm
有座位指数的桌子
有nm人想去电影院看一部新电影。他们被编号为从1到nm的整数。你应该给每个人正好一个座位。
众所周知,在这个电影院里,座位指数越低,你就越能看到屏幕上发生的一切,第i个人的视力水平为ai。让我们定义si为座位指数,它将被分配给第i个人。你想把更好的位置给视力水平较低的人,所以对于任何两个人i,j,如果ai<aj,应该满足si<sj。
在你给所有的人提供座位后,他们会开始到他们的座位上。按照从1到N的顺序,每个人都将进入大厅并坐在自己的座位上。为了去他们的位置,这个人将去他们座位的那一排,然后从这一排的第一个座位开始从左到右移动到他们的座位。在移动过程中,有些地方是空的,有些地方则被已经坐下的人占据。这个人的不便之处等于他或她将经过的被占座位的数量。
让我们考虑一个例子:m=5,这个人在第一排有4个座位,第一排的1、3、5号座位已经有人了,2、4号座位是空的。这个人的不便将是2,因为他将经过被占的1号和3号座位。
找到最小的总不便(所有的人的不便之和),这是给所有的人提供位置的可能性(所有的条件都要满足)。
输入
输入由多个测试案例组成。第一行包含一个整数t(1≤t≤100)--测试案例的数量。测试用例的描述如下。
每个测试用例的第一行包含两个整数n和m(1≤n,m≤300)--分别为每行的行数和位数。
每个测试用例的第二行包含n⋅m个整数a1,a2,...,an⋅m(1≤ai≤109),其中ai是第i个人的视力水平。
保证所有测试用例的n⋅m之和不超过105。
输出
为每个测试案例打印一个整数--可以实现的最小总不便。
例子
inputCopy
7
1 2
1 2
3 2
1 1 2 2 3 3
3 3
3 4 4 1 1 1 1 1 2
2 2
1 1 2 1
4 2
50 50 50 50 3 50 50 50
4 2
6 6 6 6 2 2 9 6
2 9
1 3 3 3 3 3 1 1 3 1 3 1 1 3 3 1 1 3
输出拷贝
1
0
4
0
0
0
1
备注
在第一个测试案例中,有一个单一的方法来分配座位:第一个人坐在第一个位置,第二个人--坐在第二个位置。总的不方便是1。
在第二个测试案例中,最佳座位是这样的。
在第三个测试案例中,最佳座位看起来是这样的。
一个单元格中的数字是坐在这个位置上的人的指数。
题解:
如果ai<aj,应该满足si<sj。每个人视力小的位置编号也要小
其次如果视力一样总排时应该把编号小的提前,
为什么?
因为对于所有的大于前面的视力y,无论编号如何肯定是要排到视力小的后面的,为了不影响后面的尽量,让小的往前
对于每一行进行排序时,我们肯定要按照规则排,视力小的一定排在前面,视力一样的,编号大的排在前面,因为肯定是编号小的先坐
然后统计每行的不满意度即可
#include<iostream>
#include<algorithm>
#include<string>
#include<queue>
#include<vector>
#include<map>
#include<cstring>
#include<cmath>
using namespace std;
#define int long long
struct node
{
int id;
int x;
}a[100040];
bool cmp(node a,node b)
{
if(a.x == b.x)
return a.id < b.id;
return a.x < b.x;
}
bool cmp1(node a,node b)
{
if(a.x == b.x)
return a.id > b.id;
return a.x < b.x;
}
void solve()
{
int n,m;
cin >> n>> m;
for(int i = 1;i <= n*m;i++)
{
cin >> a[i].x;
a[i].id = i;
}
int ans = 0;
sort(a+1,a+1+n*m,cmp);
for(int i = 1;i <= n;i ++)
{
sort(a+1+(i-1)*m,a+1+i*m,cmp1);
int l = (i-1)*m + 1,r = i * m;
for(int j = l;j <= r;j++)
{
for(int k = l;k < j;k++)
{
ans += a[j].id > a[k].id;
}
}
}
cout << ans<<"\n";
}
//32 8 32
signed main()
{
// ios::sync_with_stdio(false);
// cin.tie(0);
// cout.tie(0);
int t = 1;
cin >> t;
while(t--)
{
solve();
}
}
//10