BZOJ 3032 七夕祭

Rasine ·
更新时间:2024-09-21
· 569 次阅读

在这里插入图片描述
在这里插入图片描述
思路

交换左右相邻的两个摊点,只会改变两列中的cl感兴趣的数量,对每行的数量不会造成影响,改变上下的也是相同的道理 对于总数是否可可以被均分,决定了是否有解,即是:如果总数不能的被n整除,那么行上无解,不能被m整除,那么列上无解 针对行和列,我们单独讨论,就行而言,我们把个点的元素减去平均值,最后我们通过操作要把每个点都变成0,用f存减去平均值以后的数组的前缀和,由于第一行和最后一行看做相邻的元素,那么就转换成了一个环,问题就转换成了在把f数组看做一个一个的地址,找一个点,使得这个点到每个点的距离最小,这个最小的点就是答案

代码

#include #include #include #include using namespace std; const int N = 100010; typedef long long ll; ll a[N], b[N]; int n, m, t; ll f[N]; ll calc(ll *A, int n) { ll ans = 0; memset(f, 0, sizeof f); for (int i = 1; i <= n; i++) { A[i] -= A[0] / n; f[i] = f[i - 1] + A[i]; } sort(f + 1, f + n + 1); for (int i = 1; i <= n; i++) { ans += abs(f[i] - f[(n + 1) / 2]); } return ans; } int main() { scanf("%d%d%d", &n, &m, &t); for (int i = 1; i <= t; i++) { int x, y; scanf("%d%d", &x, &y); a[x]++; b[y]++; } for (int i = 1; i <= n; i++) a[0] += a[i]; for (int i = 1; i <= m; i++) b[0] += b[i]; if (a[0] % n == 0 && b[0] % m == 0) printf("both %lld\n", calc(a, n) + calc(b, m)); else if (a[0] % n == 0 && b[0] % m != 0) printf("row %lld\n", calc(a, n)); else if (a[0] % n != 0 && b[0] % m == 0) printf("column %lld\n", calc(b, m)); else puts("impossible"); return 0; }
作者:正月看雪花



bzoj

需要 登录 后方可回复, 如果你还没有账号请 注册新账号