思路
- 交换左右相邻的两个摊点,只会改变两列中的cl感兴趣的数量,对每行的数量不会造成影响,改变上下的也是相同的道理
- 对于总数是否可可以被均分,决定了是否有解,即是:如果总数不能的被n整除,那么行上无解,不能被m整除,那么列上无解
- 针对行和列,我们单独讨论,就行而言,我们把个点的元素减去平均值,最后我们通过操作要把每个点都变成0,用f存减去平均值以后的数组的前缀和,由于第一行和最后一行看做相邻的元素,那么就转换成了一个环,问题就转换成了在把f数组看做一个一个的地址,找一个点,使得这个点到每个点的距离最小,这个最小的点就是答案
代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int N = 100010;
typedef long long ll;
ll a[N], b[N];
int n, m, t;
ll f[N];
ll calc(ll *A, int n)
{
ll ans = 0;
memset(f, 0, sizeof f);
for (int i = 1; i <= n; i++)
{
A[i] -= A[0] / n;
f[i] = f[i - 1] + A[i];
}
sort(f + 1, f + n + 1);
for (int i = 1; i <= n; i++)
{
ans += abs(f[i] - f[(n + 1) / 2]);
}
return ans;
}
int main()
{
scanf("%d%d%d", &n, &m, &t);
for (int i = 1; i <= t; i++)
{
int x, y;
scanf("%d%d", &x, &y);
a[x]++;
b[y]++;
}
for (int i = 1; i <= n; i++)
a[0] += a[i];
for (int i = 1; i <= m; i++)
b[0] += b[i];
if (a[0] % n == 0 && b[0] % m == 0)
printf("both %lld\n", calc(a, n) + calc(b, m));
else if (a[0] % n == 0 && b[0] % m != 0)
printf("row %lld\n", calc(a, n));
else if (a[0] % n != 0 && b[0] % m == 0)
printf("column %lld\n", calc(b, m));
else
puts("impossible");
return 0;
}