[USACO18FEB]Slingshot

题意可化为:

在二维平面中有n个点,坐标为\((x_i,y_i)\),点权为\(t_i\)

现有m个询问,每次给定点\((x,y)\),求\(\min\{|x-x_i|+|y-y_i|+t_i,|y-x|\}\)

排序离散化后扫描线+分类讨论即可

#include"cstdio"
#include"cstring"
#include"iostream"
#include"algorithm"
using namespace std;

const int MAXN=1<<18;
const long long INF=1ll<<62;

int n,m,mx;
long long ans[MAXN];
long long tree[2][MAXN<<1];
struct rpg{
	int x,y;
	long long t;
	int id,rey;
}a[MAXN];

inline int read()
{
	int x=0;char ch=getchar();
	while(ch<'0'||'9'<ch) ch=getchar();
	while('0'<=ch&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x;
}

bool cmp1(rpg a,rpg b){return a.y<b.y;}
bool cmp2(rpg a,rpg b){return a.x<b.x;}

void init()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;++i) a[i].x=read(),a[i].y=read(),a[i].t=read(),a[i].id=i;
	for(int i=n+1;i<=n+m;++i) a[i].x=read(),a[i].y=read(),a[i].t=abs(a[i].y-a[i].x),a[i].id=i;
	sort(a+1,a+n+m+1,cmp1);a[1].rey=1;
	for(int i=2;i<=n+m;++i) a[i].rey=a[i].y==a[i-1].y?a[i-1].rey:a[i-1].rey+1;
	mx=a[n+m].rey;
	return;
}

void cchg(int k,int l,int r,int v,int id,bool kd)
{
	if(l==r){
		if(!kd) tree[0][k]=min(tree[0][k],a[id].y-a[id].x+a[id].t),tree[1][k]=min(tree[1][k],a[id].t-a[id].x-a[id].y);
		else tree[0][k]=min(tree[0][k],a[id].x+a[id].y+a[id].t),tree[1][k]=min(tree[1][k],a[id].x-a[id].y+a[id].t);
		return;
	}int i=k<<1,mid=l+r>>1;
	if(v<=mid) cchg(i,l,mid,v,id,kd);
	else cchg(i|1,mid+1,r,v,id,kd);
	tree[0][k]=min(tree[0][i],tree[0][i|1]);
	tree[1][k]=min(tree[1][i],tree[1][i|1]);
	return;
}

long long cask(int k,int l,int r,int le,int ri,bool kd)
{
	if(le<=l&&r<=ri) return tree[kd][k];
	int i=k<<1,mid=l+r>>1;long long mi=INF;
	if(le<=mid) mi=min(mi,cask(i,l,mid,le,ri,kd));
	if(mid<ri) mi=min(mi,cask(i|1,mid+1,r,le,ri,kd));
	return mi;
}

void solve()
{
	sort(a+1,a+n+m+1,cmp2);
	memset(tree,0x7f,sizeof(tree));
	int ct1=1,ct2=0;
	while(ct1<=n+m){
		while(ct2+1<=n+m&&a[ct2+1].x==a[ct1].x){
			++ct2;
			if(a[ct2].id<=n) cchg(1,1,mx,a[ct2].rey,ct2,0);
		}for(int i=ct1;i<=ct2;++i) if(a[i].id>n) a[i].t=min(a[i].t,min(cask(1,1,mx,1,a[i].rey,1)+a[i].y,cask(1,1,mx,a[i].rey,mx,0)-a[i].y)+a[i].x);
		ct1=ct2+1;
	}memset(tree,0x7f,sizeof(tree));
	ct1=n+m,ct2=n+m+1;
	while(ct1){
		while(ct2-1&&a[ct2-1].x==a[ct1].x){
			--ct2;
			if(a[ct2].id<=n) cchg(1,1,mx,a[ct2].rey,ct2,1);
		}for(int i=ct2;i<=ct1;++i) if(a[i].id>n) a[i].t=min(a[i].t,min(cask(1,1,mx,1,a[i].rey,1)+a[i].y,cask(1,1,mx,a[i].rey,mx,0)-a[i].y)-a[i].x);
		ct1=ct2-1;
	}for(int i=1;i<=n+m;++i) if(a[i].id>n) ans[a[i].id-n]=a[i].t;
	for(int i=1;i<=m;++i) printf("%lld\n",ans[i]);
	return;
}

int main()
{
	init();
	solve();
	return 0;
}
posted @ 2019-01-02 14:41  A·H  阅读(198)  评论(0编辑  收藏  举报