P3138 [USACO16FEB]Load Balancing S 题解

文章介绍一种方法,利用二维前缀和和离散化技术解决奶牛均匀分配到四个区域的问题,适用于小规模地图。

题目大意

给定 nnn 头奶牛,奶牛分布在农场上,每头奶牛的坐标为 (xi,yi)(x_i,y_i)(xi,yi),其中 xi≡1(mod2)x_i \equiv1 \pmod{2}xi1(mod2)yi≡1(mod2)y_i \equiv1 \pmod{2}yi1(mod2)

让你找出一条水平的线和一条竖直的线,分农场为四个区域,希望每个区域的奶牛数量平均。

求有最多奶牛的区域最少可以有说少头奶牛。

解法

二维前缀和加上离散化。

考虑到农场为 106×10610^6 \times 10^6106×106 的地图,无论是时间复杂度还是空间复杂度都太大,无法通过本题,又注意到本题只有 n≤103n \le 10^3n103,故考虑离散化处理。

对于每输入一组 (xi,yi)(x_i,y_i)(xi,yi),我们存储它的坐标和输入顺序,以便确定该点离散后的位置。这里离散化可以使用 sortsortsort 排序,记录排序后的位置即可(在这里之前存储每个点的输入顺序就有用了),新坐标为 (nxi,nyi)(nx_i,ny_i)(nxi,nyi)

开始二位前缀和,sumi,jsum_{i,j}sumi,j 表示坐标为 (i,j)(i,j)(i,j) 的点前面(包括自己)有几头牛。

枚举每一个点,然后以该点为坐标原点建立平面直角坐标系,则四个象限的牛的头数分别为:

第二象限(左上):sumi,jsum_{i,j}sumi,j

第一象限(右上):sumi,n−sumi,jsum_{i,n} - sum_{i,j}sumi,nsumi,j

第三象限(左下):sumn,j−sumi,jsum_{n,j} - sum_{i,j}sumn,jsumi,j

第四象限(右下):sumn,n+sumi,j−sumi,n−sumn,jsum_{n,n}+sum_{i,j}-sum_{i,n}-sum_{n,j}sumn,n+sumi,jsumi,nsumn,j

把这四个象限的值取 max⁡\maxmax 然后与 ansansans 比较取最小值即可。

代码

#include<bits/stdc++.h>
using namespace std;
inline void read(int &x)
{
	int f=1;
	char ch=getchar();
	x=0;
	for(;ch>57 || ch<48;ch=getchar()) if(ch==45) f=-1;
	for(;ch<=57 && ch>=48;ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
	x=x*f;
}
struct number{int order,num;};
number x[1010],y[1010];
bool cmp(number a,number b)
{
	return a.num<b.num;
}
int n,nx[1010],ny[1010],sum[1010][1010],ans=0x3f3f3f3f;
int main()
{
	read(n);
	for(register int i=1;i<=n;i++) read(x[i].num),read(y[i].num),x[i].order=y[i].order=i;
	sort(x+1,x+n+1,cmp),sort(y+1,y+n+1,cmp);
	for(register int i=1;i<=n;i++) nx[x[i].order]=i,ny[y[i].order]=i;//标记离散化后的位置 
	for(register int i=1;i<=n;i++) sum[nx[i]][ny[i]]++;
	for(register int i=1;i<=n;i++)//二维前缀和 
		for(register int j=1;j<=n;j++) sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
	for(register int i=1;i<=n;i++)
		for(register int j=1;j<=n;j++)
			ans=min(ans,max(max(sum[i][j],sum[i][n]-sum[i][j]),max(sum[n][j]-sum[i][j],sum[n][n]+sum[i][j]-sum[i][n]-sum[n][j])));
	cout<<ans;
	return 0;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值