题目链接
AcWing 105.
思路分析易错点均在代码中。
/*
1.思考什么时候输出impossible
2.思考横向交换是否影响竖向交换?
不影响。
3.单独考虑一维的最少交换情况(这里讨论行,使得每一列数量均相等)
考虑均分纸牌问题,这里是环形均分纸牌问题.
分析:
均分纸牌:
记S[i]为第i个人获得了S[i]张牌(为正则为获得牌;为负则为给出牌)
记S[0] = 0
则 S[1] = avg - a[1]
S[2] = avg - (a[2] - S[1])
.
.
.
S[k] = avg - (a[k] - S[k-1])
.
.
.
S[n-1] = avg - (a[n] - S[n-2])
sum = sigma(|S[i]|);
可以O(n)的算出答案.
环形均分纸牌问题:
!仔细思考可以发现,一定存在某两个相邻的数没有发生交换。从这个点拆开即为均分纸牌问题。
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,t;
int r[100010],c[100010];
ll a[100010],s[100010];
int main()
{
std::ios::sync_with_stdio(false);std::cin.tie(nullptr);
cin >> n >> m >> t;
for(int i=1;i<=t;i++){
int x,y;
cin >> x >> y;
// 行列互不影响,分开计算.
r[x]++;
c[y]++;
}
if(t%n!=0 && t%m!=0){ // 这里对t有范围约束,不需要考虑某一行或某一列放不下的情况.
cout << "impossible\n";
return 0;
}
bool f1 = 0,f2 = 0;
ll ans = 0;
ll avg; // 每行/列上的数量.
if(t%n==0){
f1 = 1;
avg = t / n;
for(int i=1;i<=n;i++) a[i] = r[i] - avg;
for(int i=1;i<=n;i++) s[i] = s[i-1] + a[i];
sort(s+1,s+1+n);
ll mid = s[(1+n)/2];
for(int i=1;i<=n;i++) ans += abs(s[i]-mid);
}
if(t%m==0){
f2 = 1;
avg = t / m;
for(int i=1;i<=m;i++) a[i] = c[i] - avg;
for(int i=1;i<=m;i++) s[i] = s[i-1] + a[i];
sort(s+1,s+1+m);
ll mid = s[(1+m)/2];
for(int i=1;i<=m;i++) ans += abs(s[i]-mid);
}
if(f1 && f2){
cout << "both ";
}else if(f1){
cout << "row ";
}else{
cout << "column ";
}
cout << ans << '\n';
return 0;
}