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 MBSubmit: 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
1 1
2 3
2 1 2
1 3 3
2 4 2
Sample Output
1
2