BZOJ2648: SJY摆棋子

题解:KDtree模板题 好像优秀的inline卡过去了啊

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=1e6+10;
const double eps=1e-8;
const int inf=1e9+10;
#define ll long long
using namespace std;
struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e;
void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;}
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int d,rt;
typedef struct node{
	int p[3],maxx[3],minn[3],c[2];
	friend bool operator<(node aa,node bb){
		if(aa.p[d]!=bb.p[d])return aa.p[d]<bb.p[d];
		return aa.p[3-d]<bb.p[3-d];
	}
}node;
node a[MAXN];
inline void up(int x,int y){
	for(int i=1;i<=2;i++)a[x].maxx[i]=max(a[x].maxx[i],a[y].maxx[i]),a[x].minn[i]=min(a[x].minn[i],a[y].minn[i]);
}
inline int built(int l,int r,int now){
	int mid=(l+r)>>1;
	d=now,nth_element(a+l,a+mid,a+r+1);
	for(int i=1;i<=2;i++)a[mid].minn[i]=a[mid].maxx[i]=a[mid].p[i];
	a[mid].c[0]=a[mid].c[1]=0;
	if(l<mid)a[mid].c[0]=built(l,mid-1,now%2+1),up(mid,a[mid].c[0]);
	if(r>mid)a[mid].c[1]=built(mid+1,r,now%2+1),up(mid,a[mid].c[1]);
	return mid;
}
inline void insert(int x)
{
    int *t = &rt;
    d = 1;
    while(*t) up(*t , x) , t = &a[*t].c[a[x].p[d] > a[*t].p[d]] , d = d%2+1;
    *t = x;
}
inline int dist(node x,node y){
	int ans=0;
	for(int i=1;i<=2;i++)ans+=abs(x.p[i]-y.p[i]);
	return ans;
}
inline int get_ans(node x,node y){
	int ans=0;
	for(int i=1;i<=2;i++){
		if(x.minn[i]>y.p[i])ans+=x.minn[i]-y.p[i];
		if(x.maxx[i]<y.p[i])ans+=y.p[i]-x.maxx[i];
	}
	return ans;
}
int res;
node t;
inline void querty(int x){
	if(!x)return ;
	res=min(res,dist(t,a[x]));
	int dl=(a[x].c[0]>0)?get_ans(a[a[x].c[0]],t):inf;
	int dr=(a[x].c[1]>0)?get_ans(a[a[x].c[1]],t):inf;
	if(dl<dr){
		if(dl<res)querty(a[x].c[0]);
		if(dr<res)querty(a[x].c[1]);
	}
	else{
		if(dr<res)querty(a[x].c[1]);
		if(dl<res)querty(a[x].c[0]);
	}
}
int main(){
	int n,m;n=read();m=read();
	int tot=n;
	inc(i,1,n)inc(j,1,2)a[i].p[j]=read();
	rt=built(1,n,1);
	int op,x,y;
	while(m--){
		op=read();x=read();y=read();
		if(op==1){
			tot++;
			a[tot].p[1]=a[tot].maxx[1]=a[tot].minn[1]=x;
			a[tot].p[2]=a[tot].maxx[2]=a[tot].minn[2]=y;
			a[tot].c[0]=a[tot].c[1]=0;
			insert(tot);
		}
		else{res=inf;t.p[1]=x;t.p[2]=y;querty(rt);printf("%d\n",res);}
		//if(tot%10000==0)rt=built(1,tot,1);
	}
	return 0;
}

 

2648: SJY摆棋子

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 6831  Solved: 2360
[Submit][Status][Discuss]

Description

这天,SJY显得无聊。在家自己玩。在一个棋盘上,有N个黑色棋子。他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子。此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) 。现在给出N<=500000个初始棋子。和M<=500000个操作。对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离。同一个格子可能有多个棋子。
 

Input

第一行两个数 N M
以后M行,每行3个数 t x y
如果t=1 那么放下一个黑色棋子
如果t=2 那么放下一个白色棋子

Output

对于每个T=2 输出一个最小距离
 

Sample Input

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

Sample Output


1
2

HINT

posted @ 2018-09-26 15:46  wang9897  阅读(123)  评论(0编辑  收藏  举报