BZOJ3032 七夕祭

题解

容易看出来,impossible怎么判。。
容易看出来,行和列是互不影响的
容易看出来,这是一个糖果传递
于是我就想了1h+都没有想到糖果传递怎么做。。
怎么想都只会 n 2 的,显然不可行。。
然后YY了一个错误的 O ( n )
越来越垃圾了啊
为了惩罚自己,这次写一篇博客记录一下

我们假设第i个人,给了i-1X个糖果
如果i是1,那么i-1就是n
如果X是负的就是从别人那里拿过来的
那么我们就是要让 | X 1 | + | X 2 | + | X 3 | . . . . | X n | 最小
然后我们知道每一个数最后要变成o,一开始每一个数是 a i
那么可以得到式子
a 1 X 1 + X 2 = o ,化简可得 X 2 = o a 1 + X 1
a 2 X 2 + X 3 = o ,化简可得 X 3 = o a 2 + X 2 = ( 2 o a 1 a 2 ) X 1
a 3 X 3 + X 4 = o ,化简可得 X 4 = o a 3 + X 3 = ( 3 o a 1 a 2 a 3 ) X 1
……
然后我们可以发现,一旦 X 1 固定了,剩下都出来了
并且 o a 1 ( 2 o a 1 a 2 ) ( 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;
}

猜你喜欢

转载自blog.csdn.net/qq_36797743/article/details/81007956