题意
传送门
会场由\(n\times m\)个摊位组成,cl 只对部分商品摊位感兴趣,使得所有cl 感兴趣的摊位各行各列中的一样多,调整方式只能交换相邻摊位,
两个摊位相邻当且仅当处于同一行或同一列的相邻位置,最后一行或列与第一列也是相邻的,求是否能满足行列一样多
如果行列都满足输出\(both\),满足行输出\(row\),满足列输出\(column\),如果都满足输出\(both\),都不满足输出\(impossible\)
如果能满足就输出最多的情况下求最小交换次数
数据范围
\(\begin{array}{l}1 \leq N, M \leq 100000 \\ 0 \leq T \leq \min (N \times M, 100000) \\ 1 \leq x \leq N \\ 1 \leq y \leq M\end{array}\)
题解
- 交换左右两个相邻的只会改变两列中cl感兴趣的摊位个数
- 交换上下两个相邻的只会改变两行中cl感兴趣摊位的个数
所以可以将行和列分成两个独立的来计算
- 通过最少次数的左右交换使得每列中cl感兴趣的摊位数相同
- 通过最少次数的上下交换使得每行中cl感兴趣的摊位数相同
前缀和为\(S_{k+1}-S_{k}, S_{k+2}- S_{k}, \ldots, S_{N}-S_{k}, S_{1}+S_{N}-S_{k}, \ldots, S_{N}\)
其中\(S_{N}=0\)恒成立,所以就是求一个\(k\)使得\(\sum_{i=1}^{N}|S_{i}-S_{k}|\)最小
即环形均分纸牌,对行和列分别进行均分即可,时间复杂度为\(O(n·logn+m·logm)\)
Code
#include
using namespace std;
#define ll long long
#define rep(i,a,n) for(int i=a;i>1];
rep(i,1,n+1)
ans+=abs(sumr[i]-mid);
}
if(column){
int avg=t/m;
rep(i,1,m+1) c[i]-=avg;
rep(i,1,m+1) sumc[i]=sumc[i-1]+c[i];
sort(sumc+1,sumc+m+1);
int mid=sumc[m+1>>1];
rep(i,1,m+1)
ans+=abs(sumc[i]-mid);
}
printf("%lld\n",ans);
}