luogu4169 [Violet]天使玩偶/SJY摆棋子
题解:
用cdq分治求一个点左下方最近的点的距离,然后坐标系旋转。
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 300050 const int inf = 0x7fffffff; inline int rd() { int f=1,c=0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=10*c+ch-'0';ch=getchar();} return f*c; } int n,m,ans[N],cnt,maxx,maxy; struct pnt { int x,y,tm,wt,id; }p[2*N],tmp[2*N]; struct Pair { int x,id; }px[2*N],py[2*N]; int tx[2*N],ty[2*N]; bool cmp(Pair a,Pair b) { return a.x<b.x; } bool cmpt(pnt a,pnt b) { if(a.tm!=b.tm)return a.tm<b.tm; if(a.x!=b.x)return a.x<b.x; return a.y<b.y; } void rev_x() { for(int i=1;i<=n;i++) p[i].x = maxx-p[i].x; sort(p+1,p+1+n,cmpt); for(int i=1;i<maxx;i++) { if(maxx-i>i) swap(tx[i],tx[maxx-i]); tx[i]=-tx[i]; } } void rev_y() { for(int i=1;i<=n;i++) p[i].y = maxy-p[i].y; sort(p+1,p+1+n,cmpt); for(int i=1;i<maxy;i++) { if(maxy-i>i) swap(ty[i],ty[maxy-i]); ty[i]=-ty[i]; } } struct BIT { int f[2*N]; void init(){for(int i=1;i<=maxy;i++)f[i]=-inf;} void up(int x,int d){while(x<2*N)f[x]=max(f[x],d),x+=(x&-x);} int down(int x) { int ret = -inf; while(x)ret=max(ret,f[x]),x-=(x&-x); return ret; } void clear(int x){while(x<2*N&&f[x]!=-inf)f[x]=-inf,x+=(x&-x);} }tr; void Sort(int l,int r) { int mid = (l+r)>>1; int i = l,j = mid+1,k = l; while(i<=mid&&j<=r) { while(i<=mid&&p[i].x<=p[j].x) { tmp[k] = p[i]; i++,k++; } while(j<=r&&p[i].x>p[j].x) { tmp[k] = p[j]; j++,k++; } } while(i<=mid) { tmp[k] = p[i]; i++,k++; } while(j<=r) { tmp[k] = p[j]; j++,k++; } for(i=l;i<=r;i++)p[i]=tmp[i]; } void cdq(int l,int r) { if(l==r)return ; int mid = (l+r)>>1; cdq(l,mid),cdq(mid+1,r); Sort(l,mid),Sort(mid+1,r); int i = l,j = mid+1; while(j<=r) { while(i<=mid&&p[j].x>=p[i].x) { if(p[i].wt)tr.up(p[i].y,tx[p[i].x]+ty[p[i].y]); i++; } if(p[j].id) { int now = tr.down(p[j].y); if(now!=-inf)ans[p[j].id] = min(ans[p[j].id],tx[p[j].x]+ty[p[j].y]-now); } j++; } for(i=i-1;i>=l;i--) if(p[i].wt)tr.clear(p[i].y); } int main() { n = rd(),m = rd(); for(int i=1;i<=n;i++) { px[i].x = rd(),px[i].id = i; py[i].x = rd(),py[i].id = i; p[i].tm = 0,p[i].wt = 1,p[i].id = 0; } for(int opt,x,y,i=1;i<=m;i++) { opt = rd(),x = rd(),y = rd(); n++; px[n].x = x,px[n].id = n; py[n].x = y,py[n].id = n; if(opt==1) { p[n].tm = i,p[n].wt = 1,p[n].id = 0; }else { cnt++; p[n].tm = i,p[n].wt = 0,p[n].id = cnt; } } memset(ans,0x3f,sizeof(ans)); sort(px+1,px+1+n,cmp); sort(py+1,py+1+n,cmp); for(int las=-1,i=1;i<=n;i++) { if(las!=px[i].x)las=px[i].x,maxx++,tx[maxx]=las; p[px[i].id].x = maxx; } for(int las=-1,i=1;i<=n;i++) { if(las!=py[i].x)las=py[i].x,maxy++,ty[maxy]=las; p[py[i].id].y = maxy; } maxx++,maxy++; tr.init(); sort(p+1,p+1+n,cmpt); cdq(1,n); rev_x(); cdq(1,n); rev_y(); cdq(1,n); rev_x(); cdq(1,n); for(int i=1;i<=cnt;i++) printf("%d\n",ans[i]); return 0; }