不會KD-tree怎麼辦?CQD硬搞。c++
創建正常的平面直角座標系,首先咱們只考慮在目標點左下角的點對目標點的貢獻,因爲左下點的橫縱座標都小於目標點,那麼曼哈頓距離就能夠化簡了,絕對值去掉後,獲得$x2+y2-(x1+y1)$,那麼咱們的目標就轉化爲了求橫縱座標以及時間軸都小於目標查詢點的更改點所做出的貢獻,這是一個三維偏序問題,咱們在樹狀數組中維護x+y的最大值,進而便可更新答案。數組
但是這樣作咱們只是考慮了左下角點的貢獻,確定是會出錯的,可是其他位置的點不容易化簡絕對值,或者化簡完之後的形式比較難以維護,並且我的認爲分類的話碼量略大。ide
那麼咱們換一個角度,如何將其他位置的點都變化到目標點的左下角。函數
直接翻轉座標系就好了,把全部點的橫縱座標都翻轉一下,使之分別落於其餘象限。那麼再次調用cdq便可,注意防負下標。spa
這樣打的好處就是比較無腦,並且正確性保障很大,可是常數這種東西仍是很神奇的。(本代碼不保證Bzoj可A)(其實應該不可A,由於main函數返回值是signed)3d
#include<bits/stdc++.h> #define lowbit(x) (x&(-x)) #define int long long using namespace std; const int inf=0x7fffffffffffff; int read(){ int sum=0,f=1;char x=getchar(); while(x<'0'||x>'9'){ if(x=='-') f=-1; x=getchar(); }while(x>='0'&&x<='9'){ sum=sum*10+x-'0'; x=getchar(); }return sum*f; } struct rec{ int x,y,t,id,ty; friend bool operator < (const rec &a,const rec &b){ if(a.t==b.t){ if(a.x==b.x) return a.y<b.y; else return a.x<b.x; }else return a.t<b.t; } }q[6005000],tmp[6005000]; int n,m,kind,Max,ans[3005000],tr[10005000],_time=1,mk[10005000]; void change(int pos,int val){ if(!pos) return ; for(int i=pos;i<=Max;i+=lowbit(i)) if(mk[i]!=_time){ mk[i]=_time; tr[i]=val; } else tr[i]=max(tr[i],val); } int ask(int pos){ int ans=-inf; for(int i=pos;i;i-=lowbit(i)) if(mk[i]==_time) ans=max(ans,tr[i]); return ans; } void cdq(int l,int r){ if(l==r) return ; int mid=l+r>>1; cdq(l,mid);cdq(mid+1,r); int i=l,j=mid+1,tot=l; while(i<=mid&&j<=r){ if(q[i].x<=q[j].x){ tmp[tot]=q[i]; if(!q[i].ty) change(q[i].y,q[i].x+q[i].y); ++tot;++i; }else { tmp[tot]=q[j]; if(q[j].ty) ans[q[j].id]=min(ans[q[j].id],q[j].x+q[j].y-ask(q[j].y)); ++tot;++j; } } while(i<=mid){ tmp[tot]=q[i]; // if(!q[i].ty) // change(q[i].y,q[i].x+q[i].y); ++tot;++i; } while(j<=r){ tmp[tot]=q[j]; if(q[j].ty) ans[q[j].id]=min(ans[q[j].id],q[j].x+q[j].y-ask(q[j].y)); ++tot;++j; } /* for(int i=1;i<=Max;i++) cout<<tr[i]<<" ";cout<<endl;*/ // for(int k=l;k<=mid;k++) // if(!q[i].ty) del(q[k].y); /* for(int i=1;i<=Max;i++) cout<<tr[i]<<" ";cout<<endl;*/ _time++; // if(_time>=10000000000) _time=1; for(int k=l;k<=r;k++) q[k]=tmp[k]; } signed main(){ n=read();m=read(); for(int i=1;i<=n;i++){ q[i].x=read()+1;q[i].y=read()+1; q[i].t=0;q[i].ty=0; Max=max(Max,max(q[i].x,q[i].y)); } for(int i=1;i<=m;i++){ kind=read(); if(kind&1){ q[i+n].x=read()+1;q[i+n].y=read()+1; q[i+n].t=i;q[i].ty=0; }else { q[i+n].x=read()+1;q[i+n].y=read()+1; q[i+n].t=i;q[i+n].ty=1; q[i+n].id=++ans[0]; ans[ans[0]]=inf; } Max=max(Max,max(q[i+n].x,q[i+n].y)); }n+=m; // cout<<"Max="<<Max<<endl; sort(q+1,q+n+1); cdq(1,n); /* for(int i=1;i<=n;i++) cout<<q[i].t<<" "<<q[i].x<<" "<<q[i].y<<endl;*/ for(int i=1;i<=n;i++) q[i].x=-q[i].x+Max+1; sort(q+1,q+1+n); /* for(int i=1;i<=n;i++) cout<<q[i].t<<" "<<q[i].x<<" "<<q[i].y<<endl;*/ cdq(1,n); for(int i=1;i<=n;i++) q[i].y=-q[i].y+Max+1; sort(q+1,q+1+n); cdq(1,n); for(int i=1;i<=n;i++) q[i].x=-q[i].x+Max+1; sort(q+1,q+n+1); cdq(1,n); for(int i=1;i<=ans[0];i++) printf("%lld\n",ans[i]); return 0; }