题解
容易看出来,impossible怎么判。。
容易看出来,行和列是互不影响的
容易看出来,这是一个糖果传递
于是我就想了1h+都没有想到糖果传递怎么做。。
怎么想都只会
n2
n
2
的,显然不可行。。
然后YY了一个错误的
O(n)
O
(
n
)
越来越垃圾了啊
为了惩罚自己,这次写一篇博客记录一下
我们假设第i个人,给了i-1X个糖果
如果i是1,那么i-1就是n
如果X是负的就是从别人那里拿过来的
那么我们就是要让
|X1|+|X2|+|X3|....|Xn|
|
X
1
|
+
|
X
2
|
+
|
X
3
|
.
.
.
.
|
X
n
|
最小
然后我们知道每一个数最后要变成o,一开始每一个数是
ai
a
i
那么可以得到式子
a1−X1+X2=o
a
1
−
X
1
+
X
2
=
o
,化简可得
X2=o−a1+X1
X
2
=
o
−
a
1
+
X
1
a2−X2+X3=o
a
2
−
X
2
+
X
3
=
o
,化简可得
X3=o−a2+X2=(2o−a1−a2)−X1
X
3
=
o
−
a
2
+
X
2
=
(
2
o
−
a
1
−
a
2
)
−
X
1
a3−X3+X4=o
a
3
−
X
3
+
X
4
=
o
,化简可得
X4=o−a3+X3=(3o−a1−a2−a3)−X1
X
4
=
o
−
a
3
+
X
3
=
(
3
o
−
a
1
−
a
2
−
a
3
)
−
X
1
……
然后我们可以发现,一旦
X1
X
1
固定了,剩下都出来了
并且
o−a1
o
−
a
1
,
(2o−a1−a2)
(
2
o
−
a
1
−
a
2
)
,
(3o−a1−a2−a3)
(
3
o
−
a
1
−
a
2
−
a
3
)
都是常数
那么就是给定平面上的一堆点,你要找一个X,使得X到这些点的距离最小化
那么X选中位数就可以了
记得这个模型做了一次,复习了一次,都没有记住
希望这次可以记住了
CODE:
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
typedef long long LL;
const LL N=100005;
const LL MAX=(1<<28);
LL n,m,k;
LL x[N],y[N];
LL ans=0;
LL c[N];
void solve_a()
{
LL lalal=k/n;
for (LL u=2;u<=n;u++) c[u]=c[u-1]+lalal-x[u];
sort(c+1,c+1+n);
LL mid=c[n/2+1];
for (LL u=1;u<=n;u++) ans=ans+abs(c[u]-mid);
}
void solve_b()
{
LL lalal=k/m;
for (LL u=2;u<=m;u++) c[u]=c[u-1]+lalal-y[u];
sort(c+1,c+1+m);
LL mid=c[m/2+1];
for (LL u=1;u<=m;u++) ans=ans+abs(c[u]-mid);
}
int main()
{
scanf("%lld%lld%lld",&n,&m,&k);
for (LL u=1;u<=k;u++)
{
LL xx,yy;
scanf("%lld%lld",&xx,&yy);
x[xx]++;y[yy]++;
}
if (k%n==0&&k%m==0) {printf("both ");solve_a();solve_b();printf("%lld\n",ans);return 0;}
if (k%n==0){printf("row ");solve_a();printf("%lld\n",ans);return 0;}
if (k%m==0){printf("column ");solve_b();printf("%lld\n",ans);return 0;}
printf("impossible\n");
return 0;
}