洛谷 P4169 [Violet]天使玩偶/SJY擺棋子 解題報告
阿新 • • 發佈:2018-11-28
P4169 [Violet]天使玩偶/SJY擺棋子
題目描述
\(Ayu\)在七年前曾經收到過一個天使玩偶,當時她把它當作時間囊埋在了地下。而七年後 的今天,\(Ayu\) 卻忘了她把天使玩偶埋在了哪裡,所以她決定僅憑一點模糊的記憶來尋找它。
我們把 \(Ayu\) 生活的小鎮看作一個二維平面座標系,而 \(Ayu\) 會不定時地記起可能在某個點 \((x,y)\) 埋下了天使玩偶;或者 \(Ayu\) 會詢問你,假如她在 \((x,y)\) ,那麼她離近的天使玩偶可能埋下的地方有多遠。
因為 \(Ayu\) 只會沿著平行座標軸的方向來行動,所以在這個問題裡我們定義兩個點之間的距離為\(dist(A,B)=|A_x-B_x|+|A_y-B_y|\)
輸入輸出格式
輸入格式:
第一行包含兩個整數\(n\)和\(m\) ,在剛開始時,\(Ayu\) 已經知道有\(n\)個點可能埋著天使玩偶, 接下來 \(Ayu\) 要進行 \(m\) 次操作
接下來\(n\)行,每行兩個非負整數 \((x_i,y_i)\),表示初始 \(n\) 個點的座標。
再接下來 \(m\) 行,每行三個非負整數 \(t,x_i,y_i\)。
如果 \(t=1\) ,則表示 \(Ayu\) 又回憶起了一個可能埋著玩偶的點 \((x_i,y_i)\) 。
如果 \(t=2\) ,則表示 \(Ayu\)
輸出格式:
對於每個\(t=2\)的詢問,在單獨的一行內輸出該詢問的結果。
說明
\(n,m\le 300 000\)
\(x_i,y_i\le 1 000 000\)
明明思路很簡單..
最近狀態不好啊..
考慮拆掉絕對值,然後我們會多出兩個類似於偏序型別的條件,然後配合上時間,就是一個三維偏序問題了。
討論四次可以轉換一下座標系。
注意位置是0的東西
懶得卡常吸氧氣了
Code:
// luogu-judger-enable-o2 #include <cstdio> #include <algorithm> #include <cstring> #include <cctype> const int N=6e5+10; const int M=1e6; int n,m,k,s[M+10],ans[N]; inline int read() { int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) {x=x*10+c-'0';c=getchar();} return x; } struct node{int op,x,y;}q[N],qs[N],sq[N]; int min(int x,int y){return x<y?x:y;} void add(int x,int d){while(x<=M)s[x]=s[x]>d?s[x]:d,x+=x&-x;} void Clear(int x){while(x<=M)s[x]=0,x+=x&-x;} int ask(int x){int mx=0;while(x)mx=mx>s[x]?mx:s[x],x-=x&-x;return mx==0?-M:mx;} void CDQ(int l,int r) { if(l==r) return; int mid=l+r>>1; CDQ(l,mid),CDQ(mid+1,r); register int lp=l,rp=mid+1,loc=l-1; while(lp<=mid&&rp<=r) { if(q[lp].x<=q[rp].x) { if(!q[lp].op) add(q[lp].y,q[lp].x+q[lp].y); sq[++loc]=q[lp++]; } else { if(q[rp].op) ans[q[rp].op]=min(ans[q[rp].op],q[rp].x+q[rp].y-ask(q[rp].y)); sq[++loc]=q[rp++]; } } while(rp<=r) { if(q[rp].op) ans[q[rp].op]=min(ans[q[rp].op],q[rp].x+q[rp].y-ask(q[rp].y)); sq[++loc]=q[rp++]; } for(register int i=l;i<lp;i++) if(!q[i].op) Clear(q[i].y); while(lp<=mid) sq[++loc]=q[lp++]; for(register int i=l;i<=r;i++) q[i]=sq[i]; } int main() { memset(ans,0x3f,sizeof(ans)); n=read(),m=read(); for(int i=1;i<=n;i++) qs[i].x=read()+1,qs[i].y=read()+1; for(int i=1;i<=m;i++) { qs[i+n].op=read(),qs[i+n].x=read()+1,qs[i+n].y=read()+1; if(--qs[i+n].op) qs[i+n].op=++k; } for(int i=1;i<=n+m;i++) q[i]=qs[i]; CDQ(1,n+m); for(int i=1;i<=n+m;i++) q[i]={qs[i].op,M-qs[i].x,qs[i].y}; CDQ(1,n+m); for(int i=1;i<=n+m;i++) q[i]={qs[i].op,qs[i].x,M-qs[i].y}; CDQ(1,n+m); for(int i=1;i<=n+m;i++) q[i]={qs[i].op,M-qs[i].x,M-qs[i].y}; CDQ(1,n+m); for(int i=1;i<=k;i++) printf("%d\n",ans[i]); return 0; }
2018.11.28