P4169 [Violet]天使玩偶/SJY擺棋子(CDQ分治+歐幾里得距離)
阿新 • • 發佈:2022-05-21
P4169 [Violet]天使玩偶/SJY擺棋子(CDQ分治+歐幾里得距離)
記得上一次歐幾里得距離的轉化是CF1093G Multidimensional Queries,我們使用了點對在四種方向分別考慮並用 \(\max\) 合併的方法解決,現在使用一種類似的方法。
\(\bigstar\texttt{Trick}\):
將點對的統計欽定為查詢點在修改點在右上方,這樣兩個點之間的距離就是 \((A_x+B_x)-(A_y+B_y)\)。
那麼現在只用將圖旋轉 \(\frac{\pi}{2}\times 4\),就可以覆蓋所有情況了。
對於這道題,怎麼提取出左下右上點對呢?CDQ 分治!
首先的時間限制作為第一維 \(t_1\le t_2\)
四次 CDQ 即可!
// Author:A weak man named EricQian #include<bits/stdc++.h> using namespace std; #define infll 0x3f3f3f3f3f3f3f3f #define inf 0x3f3f3f3f #define Maxn 2000005 #define pb push_back #define pa pair<int,int> #define fi first #define se second typedef long long ll; inline int rd() { int x=0; char ch,t=0; while(!isdigit(ch = getchar())) t|=ch=='-'; while(isdigit(ch)) x=x*10+(ch^48),ch=getchar(); return x=t?-x:x; } inline ll maxll(ll x,ll y){ return x>y?x:y; } inline ll minll(ll x,ll y){ return x<y?x:y; } inline ll absll(ll x){ return x>0ll?x:-x; } inline ll gcd(ll x,ll y){ return (y==0)?x:gcd(y,x%y); } int n,m,MAX; struct QUERY { int num,opt,x,y,ans; QUERY(int N=0,int O=0,int X=0,int Y=0,int A=inf): num(N),opt(O),x(X),y(Y),ans(A){} }q[Maxn<<1]; bool operator >= (QUERY a,QUERY b) { return (a.x!=b.x)?(a.x>=b.x):(a.y>=b.y); } bool cmpnum(QUERY x,QUERY y) { return x.num>y.num; } bool cmpx(QUERY x,QUERY y) { return (x.x!=y.x)?(x.x>y.x):(x.y>y.y); } struct BIT { int MIN[Maxn]; inline void init(){ memset(MIN,0x3f,sizeof(MIN)); } inline void add(int x,int val) { while(x<=1000005) MIN[x]=min(MIN[x],val),x+=x&(-x); } inline void del(int x) { while(x<=1000005) MIN[x]=inf,x+=x&(-x); } inline int query(int x) { int ret=inf; while(x) ret=min(ret,MIN[x]),x-=x&(-x); return ret; } }T; inline void Turn() { for(int i=1;i<=MAX;i++) { int x=q[i].x,y=q[i].y; q[i].x=1000005-y+1,q[i].y=x; } } void solve(int nl,int nr) { if(nl==nr) return; int mid=(nl+nr)>>1; solve(nl,mid),solve(mid+1,nr); sort(q+nl,q+mid+1,cmpx),sort(q+mid+1,q+nr+1,cmpx); int L=nl,R=mid; for(;L<=mid;L++) { if(q[L].opt==1) continue; while(R<nr && q[R+1]>=q[L]) { R++; if(q[R].opt==2) continue; T.add(1000005-q[R].y+1,q[R].x+q[R].y); } q[L].ans=min(q[L].ans,T.query(1000005-q[L].y+1)-q[L].x-q[L].y); } for(int i=mid+1;i<=R;i++) { if(q[i].opt==2) continue; T.del(1000005-q[i].y+1); } } int main() { //ios::sync_with_stdio(false); cin.tie(0); //freopen(".in","r",stdin); //freopen(".out","w",stdout); n=rd(),m=rd(),T.init(); for(int i=1,x,y;i<=n;i++) x=rd()+1,y=rd()+1,q[++MAX]=QUERY(0,1,x,y); for(int i=1,opt,x,y;i<=m;i++) opt=rd(),x=rd()+1,y=rd()+1,q[++MAX]=QUERY(i,opt,x,y); for(int tu=1;tu<=4;tu++,Turn()) sort(q+1,q+MAX+1,cmpnum),solve(1,MAX); sort(q+1,q+MAX+1,cmpnum); for(int i=MAX;i>=1;i--) if(q[i].opt==2) printf("%d\n",q[i].ans); //fclose(stdin); //fclose(stdout); return 0; }