题解:P10453 七夕祭
也许更好的阅读体验
题目传送门
最近在板刷蓝书,所以来写个题解加深自己的印象。
首先发现行和列互不影响,所以可以分开看。所以就是对行和列都做一次环形均分纸牌问题,也就是这个题糖果传递。
先来看一下普通的均分纸牌
普通的均分纸牌就是
最后每个人手里的牌一定是牌总数的平均值,即
可以这么理解,
再来看一下环形均分纸牌
环形的问题就是小朋友坐成了一圈,等同于最后一个人与第一个人相邻。
思考后可以发现环形均分纸牌的一个性质:必定至少有两个相邻的人不需要从对方那里获得纸牌(这是显然的,不妨设这两个人的位置为
所以我们可以根据上面的性质,把环变成链,枚举不需要交换的两个人。
按开始的序列顺序,像普通均分纸牌一样处理出
回到这个题
应该先判断有没有解,即行和列的
细节可以参考代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
inline int read();
int n,m,t,row[N],col[N];
long long srow[N],scol[N],rowsum,colsum,rowans,colans;
int main()
{
n=read();m=read();t=read();
for(int i=1;i<=t;i++)
{
int x,y;
x=read();y=read();
row[x]++,col[y]++;
rowsum++,colsum++;
}
if(rowsum%n!=0&&colsum%m!=0) return puts("impossible"),0;
if(rowsum%n==0)
{
int rowave=rowsum/n;
for(int i=1;i<=n;i++)
{
row[i]-=rowave;
srow[i]=srow[i-1]+row[i];
}
sort(srow+1,srow+1+n);
int k=(n+1)/2;
for(int i=1;i<=n;i++)
{
rowans+=abs(srow[i]-srow[k]);
}
}
if(colsum%m==0)
{
int colave=colsum/m;
for(int i=1;i<=m;i++)
{
col[i]-=colave;
scol[i]=scol[i-1]+col[i];
}
sort(scol+1,scol+1+m);
int k=(m+1)/2;
for(int i=1;i<=m;i++)
{
colans+=abs(scol[i]-scol[k]);
}
}
if(colsum%m!=0) printf("row %lld",rowans);
else if(rowsum%n!=0) printf("column %lld",colans);
else printf("both %lld",rowans+colans);
return 0;
}
inline int read()
{
int x=0,f=1;
char ch;
ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-') f=-f;ch=getchar();}
while(ch<='9'&&ch>='0')
{
x=(x<<1)+(x<<3)+(ch&15);
ch=getchar();
}
return x*f;
}
UPD on 2024.10.13