这天,sjy显得无聊。在家自己玩。在一个棋盘上,有 n 个黑色棋子。他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子。此处的距离是 曼哈顿距离 即 |x1−x2|+|y1−y2| 。现在给出 n≤500000 个初始棋子。和 m≤500000个操作。对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的距离。同一个格子可能有多个棋子。
input第一行两个数 n,m
以后 m 行,每行3个数 txy
如果 t=1 那么放下一个黑色棋子
如果 t=2 那么放下一个白色棋子
output对于每个 t=2 输出一个最小距离
sample input2 31 12 32 1 21 3 32 4 2sample output
12hintkdtree 可以过
题解k-d tree 膜板题
这里用的是替罪羊式加点,效率更高。
my code/**************************************************************
problem: 2648
user: infinityedge
language: c++
result: accepted
time:17728 ms
memory:48180 kb****************************************************************/#include #include #include #include #include #include #define inf 0x3f3f3f3f#define eps 1e-10using namespace std;typedef long long ll;const ll mod = 1e9 + 7;int abs(int x){
return x > 0 ? x : -x;}struct point{
int x, y;
point(){}
point(int _x, int _y){
x = _x; y = _y;
}}a[500005];int cmpx(point a, point b){
return a.x < b.x;}int cmpy(point a, point b){
return a.y < b.y;}struct node{
int x, y, siz, dt;
int dx, dy, ux, uy;
int lc, rc, fa;};struct kdtree{
node d[1000005];
int sz, rt, lst, tot;
queue q;
int newnode(){
if(!q.empty()){
int ret = q.front();
q.pop();
return lst = ret;
}
return lst = ++sz;
}
void pushup(int k){
d[k].dx = d[k].ux = d[k].x;
d[k].dy = d[k].uy = d[k].y;
d[k].siz = 1;
if(d[k].lc){
d[k].dx = min(d[k].dx, d[d[k].lc].dx);
d[k].dy = min(d[k].dy, d[d[k].lc].dy);
d[k].ux = max(d[k].ux, d[d[k].lc].ux);
d[k].uy = max(d[k].uy, d[d[k].lc].uy);
d[k].siz += d[d[k].lc].siz;
}
if(d[k].rc){
d[k].dx = min(d[k].dx, d[d[k].rc].dx);
d[k].dy = min(d[k].dy, d[d[k].rc].dy);
d[k].ux = max(d[k].ux, d[d[k].rc].ux);
d[k].uy = max(d[k].uy, d[d[k].rc].uy);
d[k].siz += d[d[k].lc].siz;
}
}
void build(int &k, int l, int r, int flag, int fa){
if(l > r) return;
k = newnode(); d[k].fa = fa; d[k].dt = flag;
// printf(%d %d %d\n, k, l, r);
if(l == r){
d[k].x = d[k].dx = d[k].ux = a[l].x; d[k].y = d[k].dy = d[k].uy = a[l].y;
return;
}
int mid = (l + r) >> 1;
if(flag) nth_element(a + l, a + mid, a + r, cmpx);
else nth_element(a + l, a + mid, a + r, cmpy);
d[k].x = a[mid].x; d[k].y = a[mid].y;
build(d[k].lc, l, mid - 1, flag ^ 1, k);
build(d[k].rc, mid + 1, r, flag ^ 1, k);
pushup(k);
}
int judge(int k){
if((d[d[k].lc].siz + 1) * 0.8 > d[k].siz + 1) return 1;
if((d[d[k].lc].siz + 1) * 0.8 > d[k].siz + 1) return 1;
return 0;
}
void dfs(int k){
q.push(k);
a[++tot] = point(d[k].x, d[k].y);
if(d[k].lc) dfs(d[k].lc);
if(d[k].rc) dfs(d[k].rc);
}
void rebuild(int k){
tot = 0;
if(k == rt){
dfs(k);
build(rt, 1, tot, 0, 0);
return;
}
int f = d[k].fa, wh = (d[f].rc == k);
dfs(k);
if(wh) build(d[f].rc, 1, tot, 0, d[f].dt ^ 1);
else build(d[f].lc, 1, tot, 0, d[f].dt ^ 1);
}
void ins(int k, int x, int y, int flag){
if(flag){
if(x <= d[k].x){
if(d[k].lc == 0){
a[1] = point(x, y);
build(d[k].lc, 1, 1, flag ^ 1, k);
}else ins(d[k].lc, x, y, flag ^ 1);
}else{
if(d[k].rc == 0){
a[1] = point(x, y);
build(d[k].rc, 1, 1, flag ^ 1, k);
}else ins(d[k].rc, x, y, flag ^ 1);
}
}else{
if(y <= d[k].y){
if(d[k].lc == 0){
a[1] = point(x, y);
build(d[k].lc, 1, 1, flag ^ 1, k);
}else ins(d[k].lc, x, y, flag ^ 1);
}else{
if(d[k].rc == 0){
a[1] = point(x, y);
build(d[k].rc, 1, 1, flag ^ 1, k);
}else ins(d[k].rc, x, y, flag ^ 1);
}
}
pushup(k);
}
void ins(int x, int y){
ins(rt, x, y, 0);
x = lst; int tmp = 0;
while(x != 0){
if(judge(x)) tmp = x;
x = d[x].fa;
}
if(tmp != 0){
rebuild(x);
}
}
int ans;
int get(int k, int x, int y){
int ret = 0;
ret += max(0, d[k].dx - x);
ret += max(0, d[k].dy - y);
ret += max(0, x - d[k].ux);
ret += max(0, y - d[k].uy);
return ret;
}
void query(int k, int x, int y){
// printf(%d %d %d\n, rt, d[k].x, d[k].y);
ans = min(ans, abs(d[k].x - x) + abs(d[k].y - y));
int dl = inf, dr = inf;
if(d[k].lc) dl = get(d[k].lc, x, y);
if(d[k].rc) dr = get(d[k].rc, x, y);
if(dl < dr){
if(dl < ans) query(d[k].lc, x, y);
if(dr < ans) query(d[k].rc, x, y);
}else{
if(dr < ans) query(d[k].rc, x, y);
if(dl < ans) query(d[k].lc, x, y);
}
}
int query(int x, int y){
ans = inf;
query(rt, x, y);
return ans;
}}kdt;int n, m;int main(){
//freopen(test.in, r, stdin);
//freopen(test.out, w, stdout);
scanf(%d%d, &n, &m);
for(int i = 1; i <= n; i ++){
int x, y;
scanf(%d%d, &x, &y);
a[i] = point(x, y);
}
kdt.build(kdt.rt, 1, n, 0, 0);
for(int i = 1; i <= m; i ++){
int opt, x, y;
scanf(%d%d%d, &opt, &x, &y);
if(opt == 1){
kdt.ins(x, y);
}else{
printf(%d\n, kdt.query(x, y));
}
}
return 0;}
浅谈电动单座调节阀的保养
上海科学院激光探测技术研究中心研发的激光雷达进入多家企业
智慧灯杆的信息管理平台架构及应用介绍
刘庆峰:让民众有对大数据和人工智能的获得感
高温熔体压力传感器
「K-D Tree 膜板」「BZOJ2648」SJY摆棋子
智能家居系统的组成
Snapchat宣布与个性化表情符号背后的Bitmoji建立合作关系
5G的发展将对物联网领域产生革命性的影响
微软安卓版 OneDrive 更新:支持三星 Motion Photos 与 8K 视频回放
未来智慧城市将有多智能,主要集中体现在那几个方面
提高人工智能道德水平的9个步骤
功率放大器的工作原理是什么
波音737MAX飞机正在接受审查将不可能在11月前进行测试飞行
如果你的周围没有5G信号,你会满城市找5G信号吗?
三星欲推出Mini LED背光电视,或将由大陆和台湾LED厂商生产
物联网的以后会是怎样的
低烟无卤阻燃控制电缆型号_低烟无卤阻燃控制电缆规格表
W波段机场异物检测FOD雷达毫米波前端解决方案
降低时序报告中逻辑延迟的方法