洛谷 P4088 [USACO18FEB] Slingshot P(线段树+二维数点)

题目链接

题意:有一个数轴,上面有 \(n\) 个传送门,使用第 \(i\) 个传送门,你可以从 \(x_i\) 走到 \(y_i\),花费的时间为 \(t_i\) 秒。你的速度为 \(1\) 格/秒,有 \(m\) 次询问,每次你要从 \(a_i\) 走到 \(b_i\),最多使用一次传送门,问最少需要多少秒。
\(1 \leq n,m \leq 10^5\)\(0 \leq a_i,b_i \leq 10^9\)

我果然是要退役了,用未去重的数组离散化(
很显然对于第 \(j\) 个询问使用第 \(i\) 个传送门的情况,需要 \(|x_i-a_j|+|y_i-b_j|+t_i\) 秒的时间。
看那个绝对值有点像曼哈顿距离……这就启发我们将题目转换为:平面上有 \(n\) 个点,第 \(i\) 个点位于 \((x_i,y_i)\),有点权 \(t_i\)。有 \(m\) 次询问,要求与 \((a_i,b_i)\) 的曼哈顿距离加上点的权值最小的点。
为什么要这么转化呢?看到平面,我们就想到二维数点。将这 \(n+m\) 个点按 \(x\) 坐标排序,暴力将绝对值拆开,分四种情况更新答案就可以了。
注意事项:对每个询问,记得赋初值 \(|b_i-a_i|\)

//Coded by tzc_wk
/*
数据不清空,爆零两行泪。
多测不读完,爆零两行泪。
边界不特判,爆零两行泪。
贪心不证明,爆零两行泪。
D P 顺序错,爆零两行泪。
大小少等号,爆零两行泪。
变量不统一,爆零两行泪。
越界不判断,爆零两行泪。
调试不注释,爆零两行泪。
溢出不 l l,爆零两行泪。
*/
#include <bits/stdc++.h>
using namespace std;
#define fi			first
#define se			second
#define fz(i,a,b)	for(int i=a;i<=b;i++)
#define fd(i,a,b)	for(int i=a;i>=b;i--)
#define foreach(it,v) for(__typeof(v.begin()) it=v.begin();it!=v.end();it++)
#define all(a)		a.begin(),a.end()
#define giveup(...) return printf(__VA_ARGS__),0;
#define fill0(a)	memset(a,0,sizeof(a))
#define fill1(a)	memset(a,-1,sizeof(a))
#define fillbig(a)	memset(a,0x3f,sizeof(a))
#define fillsmall(a) memset(a,0xcf,sizeof(a))
#define mask(a)		(1ll<<(a))
#define maskx(a,x)	((a)<<(x))
#define _bit(a,x)	(((a)>>(x))&1)
#define _sz(a)		((int)(a).size())
#define filei(a)	freopen(a,"r",stdin);
#define fileo(a)	freopen(a,"w",stdout);
#define fileio(a) 	freopen(a".in","r",stdin);freopen(a".out","w",stdout)
#define eprintf(...) fprintf(stderr,__VA_ARGS__)
#define put(x)		putchar(x)
#define eoln        put('\n')
#define space		put(' ')
#define y1			y_chenxiaoyan_1
#define y0			y_chenxiaoyan_0
#define int long long
typedef pair<int,int> pii;
inline int read(){
	int x=0,neg=1;char c=getchar();
	while(!isdigit(c)){
		if(c=='-')	neg=-1;
		c=getchar();
	}
	while(isdigit(c))	x=x*10+c-'0',c=getchar();
	return x*neg;
}
inline void print(int x){
	if(x<0){
		putchar('-');
		print(abs(x));
		return;
	}
	if(x<=9)	putchar(x+'0');
	else{
		print(x/10);
		putchar(x%10+'0');
	}
}
inline int qpow(int x,int e,int _MOD){
	int ans=1;
	while(e){
		if(e&1)	ans=ans*x%_MOD;
		x=x*x%_MOD;
		e>>=1;
	}
	return ans;
}
int _abs(int x){
	return (x<0)?-x:x;
}
int n,m;
struct ycxakioi{
	int x,y,t;
	friend bool operator <(ycxakioi ycx,ycxakioi tzc){
		return ycx.x<tzc.x;
	}
} p[200005];
struct query{
	int x,y,id,ans;
	friend bool operator <(query x,query y){
		return x.x<y.x;
	}
} q[200005];
int keyx[200005],xc,yc,keyy[200005],hsx[200005],cx,hsy[200005],cy;
struct SegTree{
	struct node{
		int l,r,mn;
	} s[200005<<2];
	inline void init(){
		fz(i,0,(200005<<2)-1)	s[i].mn=0x3f3f3f3f3f3f3f3fll;
	}
	inline void build(int k,int l,int r){
		s[k].l=l;s[k].r=r;
		if(l==r)	return;
		int mid=(l+r)>>1;
		build(k<<1,l,mid);
		build(k<<1|1,mid+1,r);
	}
	inline void modify(int k,int ind,int x){
		if(s[k].l==s[k].r){
			s[k].mn=min(s[k].mn,x);
			return;
		}
		int mid=(s[k].l+s[k].r)>>1;
		if(ind<=mid)	modify(k<<1,ind,x);
		else			modify(k<<1|1,ind,x);
		s[k].mn=min(s[k<<1].mn,s[k<<1|1].mn);
	}
	inline int query(int k,int l,int r){
		if(l<=s[k].l&&s[k].r<=r){
			return s[k].mn;
		}
		int mid=(s[k].l+s[k].r)>>1;
		if(r<=mid)	return query(k<<1,l,r);
		else if(l>mid)	return query(k<<1|1,l,r);
		else		return min(query(k<<1,l,mid),query(k<<1|1,mid+1,r));
	}
} s1,s2,s3,s4;
int anss[200005];
signed main(){
//	filei("P4088_5.in");
	n=read(),m=read();
	fz(i,1,n){
		p[i].x=read();
		p[i].y=read();
		p[i].t=read();
		keyx[++xc]=p[i].x;
		keyy[++yc]=p[i].y;
	}
	fz(i,1,m){
		q[i].x=read();
		q[i].y=read();
		q[i].id=i;
		q[i].ans=_abs(q[i].y-q[i].x);
		keyx[++xc]=q[i].x;
		keyy[++yc]=q[i].y;
	}
	sort(keyx+1,keyx+xc+1);sort(keyy+1,keyy+yc+1);
	keyx[0]=0x3f3f3f3f;keyy[0]=0x3f3f3f3f;
	fz(i,1,xc)	if(keyx[i]!=keyx[i-1])	hsx[++cx]=keyx[i];
	fz(i,1,yc)	if(keyy[i]!=keyy[i-1])	hsy[++cy]=keyy[i];
	fz(i,1,n)	p[i].x=lower_bound(hsx+1,hsx+cx+1,p[i].x)-hsx;
	fz(i,1,n)	p[i].y=lower_bound(hsy+1,hsy+cy+1,p[i].y)-hsy;
	fz(i,1,m)	q[i].x=lower_bound(hsx+1,hsx+cx+1,q[i].x)-hsx;
	fz(i,1,m)	q[i].y=lower_bound(hsy+1,hsy+cy+1,q[i].y)-hsy;
//	fz(i,1,n)	cout<<p[i].x<<" "<<p[i].y<<" "<<p[i].t<<endl;
//	fz(i,1,m)	cout<<q[i].x<<" "<<q[i].y<<endl;
	sort(p+1,p+n+1);
	sort(q+1,q+m+1);
	s1.build(1,1,cy);s2.build(1,1,cy);s3.build(1,1,cy);s4.build(1,1,cy);
	s1.init();s2.init();s3.init();s4.init();
	p[n+1].x=0x3f3f3f3f;
	int cur=1;
	fz(i,1,m){
//		if(i>=5000)	cerr<<i<<endl;
		while(p[cur].x<=q[i].x){
			s1.modify(1,p[cur].y,-hsy[p[cur].y]-hsx[p[cur].x]+p[cur].t);
			s2.modify(1,p[cur].y,hsy[p[cur].y]-hsx[p[cur].x]+p[cur].t);
			cur++;
		}
		q[i].ans=min(q[i].ans,s1.query(1,1,q[i].y)+hsx[q[i].x]+hsy[q[i].y]);
		q[i].ans=min(q[i].ans,s2.query(1,q[i].y,cy)+hsx[q[i].x]-hsy[q[i].y]);
	}
	cur=n;
	fd(i,m,1){
//		cerr<<i<<endl;
		while(p[cur].x>=q[i].x&&cur>=1){
			s3.modify(1,p[cur].y,hsy[p[cur].y]+hsx[p[cur].x]+p[cur].t);
			s4.modify(1,p[cur].y,-hsy[p[cur].y]+hsx[p[cur].x]+p[cur].t);
			cur--;
		}
		q[i].ans=min(q[i].ans,s4.query(1,1,q[i].y)-hsx[q[i].x]+hsy[q[i].y]);
		q[i].ans=min(q[i].ans,s3.query(1,q[i].y,cy)-hsx[q[i].x]-hsy[q[i].y]);
	}
	fz(i,1,m)	anss[q[i].id]=q[i].ans;
	fz(i,1,m)	cout<<anss[i]<<endl;
	return 0;
}
posted @ 2020-04-19 15:34  tzc_wk  阅读(229)  评论(1编辑  收藏  举报