1. 程式人生 > >BZOJ3032 七夕祭

BZOJ3032 七夕祭

題解

容易看出來,impossible怎麼判。。
容易看出來,行和列是互不影響的
容易看出來,這是一個糖果傳遞
於是我就想了1h+都沒有想到糖果傳遞怎麼做。。
怎麼想都只會n2的,顯然不可行。。
然後YY了一個錯誤的O(n)
越來越垃圾了啊
為了懲罰自己,這次寫一篇部落格記錄一下

我們假設第i個人,給了i-1X個糖果
如果i是1,那麼i-1就是n
如果X是負的就是從別人那裡拿過來的
那麼我們就是要讓|X1|+|X2|+|X3|....|Xn|最小
然後我們知道每一個數最後要變成o,一開始每一個數是ai
那麼可以得到式子

a1X1+X2=o,化簡可得X2=oa1+X1
a2X2+X3=o,化簡可得X3=oa2+X2=(2oa1a2)X1
a3X3+X4=o,化簡可得X4=oa3+X3=(3oa1a2a3)X1
……
然後我們可以發現,一旦X1固定了,剩下都出來了
並且oa1(2oa1a2)(3oa1a2a3)都是常數
那麼就是給定平面上的一堆點,你要找一個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; }