Problem - 1566D2 - Codeforces

电影院选座位用java表示 电影院座位编号的规律_电影院选座位用java表示

 

这是该问题的困难版本。唯一的区别是,在这个版本中,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