[POI2006]MAG-Warehouse 题解

通过这篇 常用距离算法详解,我们可以将 切比雪夫距离 转换为 曼哈顿距离

为了防止掉精度,我们需要将原坐标系中的点 \((x,y)\) 转化为 \((x+y,x-y)\) 而不是 \((\frac{x+y}{2} , \frac{x-y}{2})\)

然后可以将两个维度分开来算。此处以 \(x\) 为例

假设我们选出的坐标为 \(x\)

我们假设把每个坐标拆成 \(t_i\) 个点。

将所有 \(x_i\) 排序。

我们要使 \(\sum_{i=1}^{n} | x-x_i |\) 最小。

根据初一的知识,我们可以得出 \(x=x_{\lfloor \frac n2 \rfloor}\)

当然,根据数据范围,拆点行不通,所以可以先求出 \(t\) 的前缀和再二分查找。

根据上述过程,我们可以得出在曼哈顿距离的坐标下的答案 \((x_{ans},y_{ans})\)

但是注意到我们在之前的处理中并没有除以二,所以的出来的可能不是整点。

此处运用了 oscar 大佬的方法,直接暴力判断点就好了。

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
#define int long long
#define rep(i,a,b) for(register int i=a;i<=b;++i)
#define Rep(i,a,b) for(register int i=a;i>=b;--i)
inline int read()
{
    bool f=0;int x=0;char ch;
    do{ch=getchar();f|=(ch=='-');}while(!isdigit(ch));
    do{x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}while(isdigit(ch));
    return f?-x:x;
}
inline void write(int x)
{
    if(x<0)x=-x,putchar('-');
    if(x>9)write(x/10);putchar(x%10+'0');
}
inline void writesp(int x)
{
	write(x);putchar(' ');
}
inline void writeln(int x)
{
	write(x);puts("");
}
struct node1
{
	int x;
	int t;
	bool operator <(const node1 &b)const
	{
		return x<b.x;
	}
}x[maxn];
struct node2
{
	int y;
	int t;
	bool operator <(const node2 &b)const
	{
		return y<b.y;
	}
}y[maxn];
int qx[maxn],qy[maxn],qz[maxn];
int n;
int sumx[maxn],sumy[maxn];
int check(int xx,int yy)
{
	int ans=0;
	rep(i,1,n)
	{
		ans+=max(abs(xx-qx[i]),abs(yy-qy[i]))*qz[i];
	}
	return ans;
}
signed main()
{
	n=read();
	rep(i,1,n)
	{
		int a=read(),b=read();
		x[i].x=a+b;y[i].y=a-b;
		qz[i]=x[i].t=y[i].t=read();
		qx[i]=a;qy[i]=b;
	}
	sort(x+1,x+1+n);
	sort(y+1,y+1+n);
	rep(i,1,n)sumx[i]=sumx[i-1]+x[i].t;
	rep(i,1,n)sumy[i]=sumy[i-1]+y[i].t;
	int tempx=sumx[n],tempy=sumy[n];
	rep(i,1,n)sumx[i]<<=1;
	rep(i,1,n)sumy[i]<<=1;
	int posx=lower_bound(sumx+1,sumx+1+n,tempx)-sumx;
	int posy=lower_bound(sumy+1,sumy+1+n,tempy)-sumy;
	int sx=x[posx].x,sy=y[posy].y;
	int nx=((sx+sy)/2),ny=((sx-sy)/2);
	int ans1=check(nx,ny),ans2=check(nx+1,ny),ans3=check(nx,ny+1),ans4=check(nx+1,ny+1);
	if(ans4<=ans3&&ans4<=ans2&&ans4<=ans1)     printf("%d %d\n",nx+1,ny+1);
	else if(ans3<=ans4&&ans3<=ans2&&ans3<=ans1)printf("%d %d\n",nx,ny+1);
	else if(ans2<=ans4&&ans2<=ans3&&ans2<=ans1)printf("%d %d\n",nx+1,ny);
	else if(ans1<=ans2&&ans1<=ans3&&ans1<=ans4)printf("%d %d\n",nx,ny);
	return 0;
}
posted @ 2020-11-05 08:40  ฅ(OωO)ฅ  阅读(143)  评论(0)    收藏  举报
"scale": 1 }, "display": { "position": "left", "width": 100, "height": 200, "hOffset": 70, "vOffset": 0 }, "mobile": { "show": true, "scale": 0.5 }, "react": { "opacityDefault": 0.7, "opacityOnHover": 0.2 } }); window.onload = function(){ $("#live2dcanvas").attr("style","position: fixed; opacity: 0.7; left: 70px; bottom: 0px; z-index: 1; pointer-events: none;") } -->