题目大意:
有个
N∗M
N
∗
M
的矩形,
cl
c
l
有
T
T
个感兴趣的摊点,问如何移动使得各行中
cl
c
l
感兴趣的摊点数一样多,并且各列中
cl
c
l
感兴趣的摊点数也一样多。
每次移动能将左右相邻或者上下相邻的交换,头尾也算相邻。
问两个要求最多能满足多少个。在此前提下,至少需要交换多少次摊点。
1≤N,M≤100000
1
≤
N
,
M
≤
100000
0≤T≤min(NM,100000)
0
≤
T
≤
m
i
n
(
N
M
,
100000
)
1≤Xi≤N,1≤Yi≤M
1
≤
X
i
≤
N
,
1
≤
Y
i
≤
M
分析:
代码:
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#define N 100005
using namespace std;
typedef long long ll;
ll a[N], b[N], s[N];
int n, m, T;
ll Get_num(ll *C, int tot)
{
for (int i = 1; i <= tot; i++)
{
ll x = C[i] - T / tot;
s[i] = s[i - 1] + x;
}
sort(s + 1, s + tot + 1);
ll rp = 0, cp = s[(tot + 1) >> 1];
for (int i = 1; i <= tot; i++)
rp += fabs(s[i] - cp);
return rp;
}
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];
}
int ans = 0;
if (T % n == 0) ans += Get_num(a, n);
if (T % m == 0) ans += Get_num(b, m);
if (T % n == 0 && T % m == 0) printf("both %lld\n", ans);
else if (T % n == 0) printf("row %lld\n", ans);
else if (T % m == 0) printf("column %lld\n", ans);
else printf("impossible\n");
return 0;
}