习题:七夕祭(杂题)
题目

思路
首先一点如果是impossible,那么一定
\(T\%N\)和\(T\%M\)都不为0
再接着,
因为竖着满足跟横着满足本质上是一样的,所以这里只讨论横着满足
并且如果要满足横着的情况,
如果要步数最小,那么我们一定不会将竖着的摊位交换
同理,如果要满足竖着的情况,我们一定不会将横着的摊位交换
也就是说如果我们定义两个数组row和col来维护每一行和每一列的摊位个数
那么竖着交换对col数组没有任何影响,横着交换对row数组也没有任何影响
也就是指,如果是both的话,
我们只需要将横着交换的最小值和竖着交换的最小值相加即可
因为我们只需要横着满足,所以我们其实并不在意整个矩阵长成什么样子
我们所需要知道的,只是每一横着有多少个摊点
问题转换为:
现在我们有一个环,我们只能使相邻的元素一个+1,一个-1,求最小的步数使这个数列的元素变为一样
然后?
这个模型你们不熟悉?
如果真不熟悉的话,
蒟蒻笔者还是解释一下
t就是题意中的t
我们先对于每一个元素求出他到指定元素的差距,即\(row_i=row_i-t/n\)
接着求出前缀和数组\(srow\),然后求出对\(srow\)排序之后的中点\(mid=srow_{(n+1)/2}\),n+1是防止精度
最后\(ans=\sum_{i=1}^{n}abs(srow_i-mid)\)
你可以用方程思想去理解
我们设原本每一个元素为\(a_i\)
第i个元素向第i-1个元素的贡献为\(x_i\)
一定有方程
\(\frac{t}{n}=a_i-x_i+x_{i+1}\)
这样还看不出什么来
但是如果你用主元的思想
我们再设\(c_j=\sum_{i=1}^{j}a_i-j*\frac{t}{n}\)
\(\frac{t}{n}=a_i-x_i+x_{i+1}\)
\(\begin{aligned}x_2&=\frac{t}{n}-a_1+x_1\\&=x_1-c_1\end{aligned}\)
同理
\(\begin{aligned}x_3&=\frac{t}{n}-a_2+x_2\\&=\frac{t}{n}-a_2+x_1-c_1\\&=\frac{t}{n}-a_2+x_1+\frac{t}{n}-a_1\\&=x_1-c_2\end{aligned}\)
之后
\(x_i=x_1-c_i\)
答案是什么?
\(\begin{aligned}ans&=\sum_{i=1}^{n}x_i\\&=\sum_{i=1}^{n}|x_1-c_i|\end{aligned}\)
之后?
\(c_i\)已知,也就是说ans只和\(x_1\)有关
并且我们要求最小值,
之后,\(x_1\) 不就是数组\(c\)的中位数?
代码
#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
struct node
{
int x,y;
}a[200005];
int n,m,t;
int col[200005];
int row[200005];
int s_row[200005];
int s_col[200005];
int ans_row;
int ans_col;
int f_abs(int x)
{
if(x<0)
return -x;
return x;
}
signed main()
{
cin>>n>>m>>t;
if(t%n!=0&&t%m!=0)
{
cout<<"impossible";
return 0;
}
for(int i=1;i<=t;i++)
{
cin>>a[i].x>>a[i].y;
row[a[i].x]++;
col[a[i].y]++;
}
if(t%n==0)
{
for(int i=1;i<=n;i++)
row[i]=row[i]-t/n;
for(int i=1;i<=n;i++)
s_row[i]=s_row[i-1]+row[i];
sort(s_row+1,s_row+1+n);
int mid=s_row[(n+1)/2];
for(int i=1;i<=n;i++)
ans_row+=f_abs(mid-s_row[i]);
}
if(t%m==0)
{
for(int i=1;i<=m;i++)
col[i]=col[i]-t/m;
for(int i=1;i<=m;i++)
s_col[i]=s_col[i-1]+col[i];
sort(s_col+1,s_col+1+m);
int mid=s_col[(m+1)/2];
for(int i=1;i<=m;i++)
ans_col+=f_abs(mid-s_col[i]);
}
if(t%n==0&&t%m==0)
{
cout<<"both "<<ans_row+ans_col;
return 0;
}
if(t%n==0)
{
cout<<"row "<<ans_row;
return 0;
}
if(t%m==0)
{
cout<<"column "<<ans_col;
return 0;
}
return 0;
}

浙公网安备 33010602011771号