生活随笔
收集整理的這篇文章主要介紹了
P4169 [Violet]天使玩偶/SJY摆棋子(CDQ分治、暴力)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
解析
之前用KDtree做的一道題
由于懶不想再碼一遍了
考慮CDQ分治
關鍵就是如何拿掉絕對值
如果只維護左下角的,顯然就是一個經典的三維偏序問題了
但是本題不一定在左下角,也可能在左上、右下、右上
怎么辦?
把坐標翻轉翻轉直接暴力做四遍即可
有昨晚CFE題暴力枚舉做36遍那味了
代碼
既然沒寫,哪里有代碼啊
那我就把之前的KDtree貼一下吧
#include<bits/stdc++.h>
using namespace std
;
#define ll long long
const int N
=2e6+100;
const int M
=1050;
const int mod
=998244353;
inline ll
read(){ll x
=0,f
=1;char c
=getchar();while(!isdigit(c
)){if(c
=='-') f
=-1;c
=getchar();}while(isdigit(c
)){x
=x
*10+c
-'0';c
=getchar();}return x
*f
;
}
int n
,m
,tot
,num
;
int rub
[N
],top
;
int F
;
struct point{int x
[2];}p
[N
];
#define dis(a,b) (abs(a.x[0]-b.x[0])+abs(a.x[1]-b.x[1]))
bool operator < (const point a
,point b
){return a
.x
[F
]<b
.x
[F
];}
struct node{int mn
[2],mx
[2],ls
,rs
,siz
;point o
;
}tr
[N
];
int New(point u
){int x
=top
?rub
[top
--]:++tot
;tr
[x
].o
=u
;tr
[x
].siz
=1;tr
[x
].mn
[0]=tr
[x
].mx
[0]=u
.x
[0];tr
[x
].mn
[1]=tr
[x
].mx
[1]=u
.x
[1];tr
[x
].ls
=tr
[x
].rs
=0;return x
;
}
void pushup(int k
){int l
=tr
[k
].ls
,r
=tr
[k
].rs
;for(int i
=0;i
<=1;i
++){tr
[k
].mn
[i
]=tr
[k
].mx
[i
]=tr
[k
].o
.x
[i
];if(l
){tr
[k
].mn
[i
]=min(tr
[k
].mn
[i
],tr
[l
].mn
[i
]);tr
[k
].mx
[i
]=max(tr
[k
].mx
[i
],tr
[l
].mx
[i
]);}if(r
){tr
[k
].mn
[i
]=min(tr
[k
].mn
[i
],tr
[r
].mn
[i
]);tr
[k
].mx
[i
]=max(tr
[k
].mx
[i
],tr
[r
].mx
[i
]);}}tr
[k
].siz
=tr
[l
].siz
+tr
[r
].siz
+1;return;
}
void print(int k
){printf("k=%d (%d %d) ls=%d rs=%d mn=(%d %d) mx=(%d %d)\n",k
,tr
[k
].o
.x
[0],tr
[k
].o
.x
[1],tr
[k
].ls
,tr
[k
].rs
,tr
[k
].mn
[0],tr
[k
].mn
[1],tr
[k
].mx
[0],tr
[k
].mx
[1]);
}
int build(int l
,int r
,int f
){int mid
=(l
+r
)>>1;F
=f
;nth_element(p
+l
,p
+mid
,p
+r
+1);int k
=New(p
[mid
]);if(l
<mid
) tr
[k
].ls
=build(l
,mid
-1,f
^1);if(mid
<r
) tr
[k
].rs
=build(mid
+1,r
,f
^1);pushup(k
);return k
;
}
void pia(int k
,int num
){if(tr
[k
].ls
) pia(tr
[k
].ls
,num
);p
[num
+tr
[tr
[k
].ls
].siz
+1]=tr
[k
].o
;if(tr
[k
].rs
) pia(tr
[k
].rs
,num
+tr
[tr
[k
].ls
].siz
+1);rub
[++top
]=k
;return;
}
double A
=0.95;
void check(int &k
,int f
){if(tr
[tr
[k
].ls
].siz
>tr
[k
].siz
*A
||tr
[tr
[k
].rs
].siz
>tr
[k
].siz
*A
){pia(k
,0);k
=build(1,tr
[k
].siz
,f
);}return;
}
void insert(int &k
,int f
,point u
){if(!k
){k
=New(u
);return;}if(u
.x
[f
]<=tr
[k
].o
.x
[f
]) insert(tr
[k
].ls
,f
^1,u
);else insert(tr
[k
].rs
,f
^1,u
);pushup(k
);check(k
,f
);return;
}
int getdis(point o
,int k
){int res
=0;for(int i
=0;i
<=1;i
++){res
+= max(0,tr
[k
].mn
[i
]-o
.x
[i
])+max(0,o
.x
[i
]-tr
[k
].mx
[i
]);}return res
;
}
int ans
;
void query(int k
,point tmp
) {ans
=min(ans
,dis(tmp
,tr
[k
].o
));int dl
=INT_MAX
,dr
=INT_MAX
;if(tr
[k
].ls
) dl
=getdis(tmp
,tr
[k
].ls
);if(tr
[k
].rs
) dr
=getdis(tmp
,tr
[k
].rs
);if(dl
<dr
) {if(dl
<ans
) query(tr
[k
].ls
,tmp
);if(dr
<ans
) query(tr
[k
].rs
,tmp
);}else {if(dr
<ans
) query(tr
[k
].rs
,tmp
);if(dl
<ans
) query(tr
[k
].ls
,tmp
);}
}
int r
;
int main(){
n
=read();m
=read();for(int i
=1;i
<=n
;i
++){p
[i
]=(point
){read(),read()};}r
=build(1,n
,0);for(int i
=1;i
<=m
;i
++){int op
=read(),x
=read(),y
=read();point o
=(point
){x
,y
};if(op
==1){insert(r
,0,o
);}else{ans
=2e9;query(r
,o
);printf("%d\n",ans
);}}return 0;
}
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎
總結
以上是生活随笔為你收集整理的P4169 [Violet]天使玩偶/SJY摆棋子(CDQ分治、暴力)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。