[bzoj3032][數論][中位數]七夕祭
Description
七夕節因牛郎織女的傳說而被扣上了「情人節」的帽子。於是TYVJ今年舉辦了一次線下七夕祭。Vani同學今年成功邀請到了cl同學陪他來共度七夕,於是他們決定去TYVJ七夕祭遊玩。
TYVJ七夕祭和11區的夏祭的形式很像。矩形的祭典會場由N排M列共計N×M個攤點組成。雖然攤點種類繁多,不過cl只對其中的一部分攤點感興趣,比如章魚燒、蘋果糖、棉花糖、射的屋……什麼的。Vani預先聯絡了七夕祭的負責人zhq,希望能夠通過恰當地佈置會場,使得各行中cl感興趣的攤點數一樣多,並且各列中cl感興趣的攤點數也一樣多。
不過zhq告訴Vani,攤點已經隨意佈置完畢了,如果想滿足cl的要求,唯一的調整方式就是交換兩個相鄰的攤點。兩個攤點相鄰,當且僅當他們處在同一行或者同一列的相鄰位置上。由於zhq率領的TYVJ開發小組成功地扭曲了空間,每一行或每一列的第一個位置和最後一個位置也算作相鄰。現在Vani想知道他的兩個要求最多能滿足多少個。在此前提下,至少需要交換多少次攤點。
Input
第一行包含三個整數N和M和T。T表示cl對多少個攤點感興趣。 接下來T行,每行兩個整數x,
y,表示cl對處在第x行第y列的攤點感興趣。
Output
首先輸出一個字串。如果能滿足Vani的全部兩個要求,輸出both;如果通過調整隻能使得各行中cl感興趣的攤點數一樣多,輸出row;如果只能使各列中cl感興趣的攤點數一樣多,輸出column;如果均不能滿足,輸出impossible。
如果輸出的字串不是impossible, 接下來輸出最小交換次數,與字串之間用一個空格隔開。
Sample Input
樣例輸入1
2 3 4
1 3
2 1
2 2
2 3
樣例輸入2
3 3 3
1 3
2 2
2 3
Sample Output
樣例輸出1
row 1
樣例輸出2
both 2
HINT
對於100% 的資料,1≤N, M≤100000,0≤T≤min(NM, 100000),1≤x≤N,1≤y≤M。
題解
頹完課內1個月後的我終於來更blog了。。。
(其實只是因為在刷51nod不想更2333
今早看到這題還是想了挺久的。。我怎麼這麼菜
首先你會發現一個性質,對於兩個挨在一起的相同格子當然不用交換這tm不是廢話嗎
然後又會有一個性質
假設我們當前已經調整到行相同了,那麼在調整列相同的時候行的答案是一定不會變的
為啥?畫個圖看看就知道了嘛
於是這就變成了一個裸的糖果傳遞
把每行看成一個人,每列看成一個人,交換行的時候列所擁有的糖果數是不會變的,反之亦然。隨便跑一跑糖果傳遞就沒了
判無解的話判一判能不能整除就好了嘛。。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
int a[110000],n,m,T;
int X[110000],Y[110000];
int s[110000];
int main()
{
scanf("%d%d%d",&n,&m,&T);
for(int i=1;i<=T;i++)scanf("%d%d",&X[i],&Y[i]);
if(T%n!=0 && T%m!=0){printf("impossible\n");return 0;}
else if(T%n==0 && T%m!=0)//行可以列不可以
{
printf("row\n");
for(int i=1;i<=T;i++)a[X[i]]++;
int ave=T/n;
for(int i=1;i<=n;i++)s[i+1]=s[i]+a[i]-ave;
sort(s+1,s+1+n);
LL ans=0;int md=(n+1)/2;
for(int i=1;i<=n;i++)ans+=(LL)abs(s[i]-s[md]);
printf("%lld\n",ans);
}
else if(T%m==0 && T%n!=0)//行可以列不可以
{
printf("column\n");
for(int i=1;i<=T;i++)a[Y[i]]++;
int ave=T/m;
for(int i=1;i<=m;i++)s[i+1]=s[i]+a[i]-ave;
sort(s+1,s+1+m);
LL ans=0;int md=(m+1)/2;
for(int i=1;i<=m;i++)ans+=(LL)abs(s[i]-s[md]);
printf("%lld\n",ans);
}
else
{
printf("both\n");
for(int i=1;i<=T;i++)a[X[i]]++;
int ave=T/n;
for(int i=1;i<=n;i++)s[i+1]=s[i]+a[i]-ave;
sort(s+1,s+1+n);
LL ans=0;int md=(n+1)/2;
for(int i=1;i<=n;i++)ans+=(LL)abs(s[i]-s[md]);
memset(a,0,sizeof(a));
for(int i=1;i<=T;i++)a[Y[i]]++;
ave=T/m;
for(int i=1;i<=m;i++)s[i+1]=s[i]+a[i]-ave;
sort(s+1,s+1+m);md=(m+1)/2;
for(int i=1;i<=m;i++)ans+=(LL)abs(s[i]-s[md]);
printf("%lld\n",ans);
}
return 0;
}