列表

详情


NC51118. 天使玩偶

描述

Ayu在七年前曾经收到过一个天使玩偶,当时她把它当做时间囊埋在了地下。
而七年后的今天,Ayu却忘了她把天使玩偶埋在了哪里,所以她决定仅凭一点模糊的记忆来寻找它。
我们把Ayu生活的小镇看做一个二维平面直角坐标系,而Ayu会不定时的记起可能在某个点(x,y)埋下了天使玩偶。
或者Ayu会询问你,假如她在(x,y),那么她离最近的天使玩偶可能埋下的地方有多远。
因为Ayu只会沿着平行坐标轴的方向来行动,所以在这个问题里我们定义两个点之间的距离为曼哈顿距离:

其中A_x表示点A的横坐标,其余类似。

输入描述

第一行包含两个整数n和m,在刚开始时,Ayu已经知道有n个点可能埋着天使玩偶,接下来Ayu要进行m次操作。
接下来n行,每行两个非负整数xi,yi,表示初始n个点的坐标。
再接下来m行,每行三个非负整数 t,x,y 。
如果t=1,表示Ayu又回忆起了一个可能埋着玩偶的点(x,y)。
如果t=2,表示Ayu询问如果她在坐标(x,y),那么在已经回忆出的点里,离她最近的那个点有多远。

输出描述

对于每个t=2的询问,在单独的一行内输出该询问的结果。

示例1

输入:

2 3
1 1
2 3
2 1 2
1 3 3
2 4 2

输出:

1
2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 3574ms, 内存消耗: 55132K, 提交时间: 2021-07-18 20:37:15

#include<iostream>
#include<cstring>
using namespace std;
#define lowbit(x) ((x)&(-x))
const int N = 1e6+10;
struct node{
	int x,y,f,id;
}a[N],b[N],c[N];
int n,m,cnt;
int tr[N],M=-1e9;
void add(int x,int v){for(int i=x;i<=M;i+=lowbit(i)) tr[i] = max(tr[i],v);}
int query(int x){int res = 0;for(int i=x;i;i-=lowbit(i)) res=max(res,tr[i]); return res;}
void cls(int x){for(int i=x;i<=M;i+=lowbit(i)) tr[i]=0;}

int num[N],ans[N];
void CDQ(int ll,int rr){
	if(ll==rr) return;
	int mid = (ll+rr)>>1;
	CDQ(ll,mid),CDQ(mid+1,rr);
	
	int t1=ll,t2=mid+1,p=ll;
	while(t2<=rr){
		while(t1<=mid&&a[t1].x<=a[t2].x){
			if(a[t1].f==1) add(a[t1].y,a[t1].x+a[t1].y);
			b[p++]=a[t1++];
		}
		if(a[t2].f==2){
			int tt = query(a[t2].y);
			if(tt) ans[a[t2].id] = min(ans[a[t2].id],a[t2].x+a[t2].y-tt);
		}
		b[p++]=a[t2++];
	}
	for(int i=ll;i<t1;i++) cls(a[i].y);
	
	while(t1<=mid) b[p++]=a[t1++];
    while(t2<=rr) b[p++]=a[t2++];
    for(int i=ll;i<=rr;++i) a[i]=b[i];
	
}

void init(int d){
	int mxx=0,myy=0;cnt=0;
	for(int i=1;i<=n+m;i++){
		if(d==1) c[i].x = M-c[i].x;
		else if(d==2) c[i].y = M-c[i].y;
		if(c[i].f==2) mxx=max(mxx,c[i].x),myy=max(myy,c[i].y);
	}
	for(int i=1;i<=n+m;i++){
		if(c[i].x<=mxx&&c[i].y<=myy) a[++cnt] = c[i];
	}
}

int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		c[i].id=i,c[i].f=1;
		scanf("%d%d",&c[i].x,&c[i].y);
		c[i].x++,c[i].y++;
		M = max(M,max(c[i].x,c[i].y));
	}
	for(int i=n+1;i<=n+m;i++){
		scanf("%d%d%d",&c[i].f,&c[i].x,&c[i].y);
		c[i].id = i;
		c[i].x++,c[i].y++;
		if(c[i].f==2) num[++num[0]] = i;ans[i] = 1e9;
		M = max(M,max(c[i].x,c[i].y));
	}
	M++;
	init(0),CDQ(1,cnt);
	init(1),CDQ(1,cnt);
	init(2),CDQ(1,cnt);
	init(1),CDQ(1,cnt);
	for(int i=1;i<=num[0];i++) printf("%d\n",ans[num[i]]);
	
	return 0;
}

上一题