P4876 The Lazy Cow G 非常神奇有意思

Tang Problem

题意

\(n\) 个草地的坐标(相当于点),我们需要选择一个点,使得与他距离小于等于 \(k\) 的草地最多。

这里定义的距离就是从起点开始,可以往东西南北走,一次走一个单位长度,最短到达目的地的行走次数。

做法

这个做法需要会切比雪夫距离和曼哈顿距离的互化,并且熟练掌握了扫描线。

这个也是好做的,我们很好想到这个使用扫描线是可以做的,暴力扫 x 轴,数据结构维护 y 轴,合法区域就像一个菱形一样,理论上 \(O(nlogn)\) 是可以做的。

但问题就是这个菱形并不是正的,而是歪的,让我们维护起来就十分的头大。

为什么这个是歪的?自然是因为这个距离的计算方式其实就是曼哈顿距离。

我们把这个转化称切比雪夫距离不就相当于将这个摆正了吗?

所以我们转化一下,\((x,y)\to(x+y,x-y)\)

之后我们就很容易使用扫描线求解了。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
namespace DataStructure{
	const int MN=1e6+116;
	struct Segmentree{
		#define lc k<<1
		#define rc k<<1|1
		struct Node{
			int l, r, maxn, tag;
		}tr[MN];
		void pushup(int k){
			tr[k].maxn=max(tr[lc].maxn,tr[rc].maxn);
		}
		void build(int k, int l, int r){
			tr[k].l=l, tr[k].r=r; tr[k].tag=0;
			if(l==r){tr[k].maxn=0; return;}
			int mid=(l+r)>>1;
			build(lc,l,mid);
			build(rc,mid+1,r);
			pushup(k); return;
		}
		void pushdown(int k){
		    if(tr[k].tag==0) return;
		    tr[lc].maxn+=tr[k].tag;
		    tr[rc].maxn+=tr[k].tag;
		    tr[lc].tag+=tr[k].tag;
		    tr[rc].tag+=tr[k].tag;
		    tr[k].tag=0;
		}
		void update(int k, int l, int r, int val){
			if(tr[k].l>=l&&tr[k].r<=r){
				tr[k].maxn+=val; tr[k].tag+=val; return;}
			pushdown(k); int mid=(tr[k].l+tr[k].r)>>1;
			if(l<=mid) update(lc,l,r,val);
			if(r>mid) update(rc,l,r,val);
			pushup(k); return;
		}
	};
}
int n, k;
const int MN=1e6+116;
DataStructure::Segmentree tr;
struct Node{
	int x, y1, y2, id;
	bool operator < (const Node &o) const{
		if(x!=o.x) return x<o.x;
		return id>o.id;
	}
}point[MN],query[MN];
int lsh[MN], ans=0;
int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); cin>>n>>k;
	for(int i=1,val,xa,ya; i<=n; ++i){
		cin>>val>>xa>>ya;
		xa+=ya; ya=xa-ya*2;
		int xb=xa+2*k, yb=ya+2*k;
		point[i*2-1]={xa,ya,yb,val};
		point[i*2]={xb,ya,yb,-val};
		lsh[i*2-1]=ya; lsh[i*2]=yb;
	}
	sort(point+1,point+n*2+1);
	sort(lsh+1,lsh+n*2+1);
	int len=unique(lsh+1,lsh+n*2+1)-lsh-1;
	tr.build(1,1,len-1);
	for(int i=1; i<n*2; ++i){
		int ya=lower_bound(lsh+1,lsh+len+1,point[i].y1)-lsh;
		int yb=lower_bound(lsh+1,lsh+len+1,point[i].y2)-lsh;
		tr.update(1,ya,yb,point[i].id);
		ans=max(ans,tr.tr[1].maxn);
	}
	cout<<ans<<'\n';
	return 0;
}
posted @ 2025-08-23 09:05  BaiBaiShaFeng  阅读(12)  评论(0)    收藏  举报
Sakana Widget右下角定位