[Violet]天使玩偶/SJY摆棋子——k-d tree & Scapegoat tree

BZOJ2648-SJY摆棋子题解
本文详细介绍了BZOJ2648-SJY摆棋子问题的在线解法,利用k-d树结合scapegoattree维护平衡,实现动态查询离某点曼哈顿距离最近的点。代码示例展示了具体的实现细节。

BZOJ 2648-SJY摆棋子

题目大意

一堆点,可以加点,询问离某个点曼哈顿距离最近的点的曼哈顿距离

Solution

离线做法:cdq分治,代码量蛮短的

这里主要讲在线做法
这是k-d tree的模板题,但是因为有加点操作,所以不能保证k-dtree的重量平衡,可能会使这棵BST的结构变得很难看,随便一卡就能卡掉

所以我们要加上Scapegoat tree来暴力维护它的相对平衡

Code

#include <cstdio>
#include <iostream>
#include <algorithm>
#define al 0.75
#define N 1000010
#define INF 0x3f3f3f3f

using namespace std;

int rub[N], WD, top, root, cur, ans;

struct Point {
    int x[2];
    Point(int X = 0, int Y = 0) {
        x[0] = X;
        x[1] = Y;
    }
    inline bool operator < (const Point &o) const {
        return x[WD] < o.x[WD];
    }
}p[N];

struct Node {
    int mi[2], mx[2], ls, rs, sz;
    Point p;
}tr[N];

inline int read() {
    char ch = getchar();
    int x = 0;
    while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch)) {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x;
}

inline int newNode() {
    if (top) return rub[top--];
    return ++cur;
}

inline void pushup(int k) {
    int l = tr[k].ls, r = tr[k].rs;
    for (int i = 0; i < 2; ++i) {
        tr[k].mi[i] = tr[k].mx[i] = tr[k].p.x[i];
        if (l) {
            tr[k].mi[i] = min(tr[k].mi[i], tr[l].mi[i]);
            tr[k].mx[i] = max(tr[k].mx[i], tr[l].mx[i]);
        }
        if (r) {
            tr[k].mi[i] = min(tr[k].mi[i], tr[r].mi[i]);
            tr[k].mx[i] = max(tr[k].mx[i], tr[r].mx[i]);
        }
    }
    tr[k].sz = tr[l].sz + tr[r].sz + 1;
}

inline int build(int l, int r, int wd) {
    if (l > r) return 0;
    int k = newNode(), mid = l + r >> 1;
    WD = wd;
    nth_element(p + l, p + mid, p + r + 1);
    tr[k].p = p[mid];
    tr[k].ls = build(l, mid - 1, wd ^ 1);
    tr[k].rs = build(mid + 1, r, wd ^ 1);
    pushup(k);
    return k;
}

inline void pia(int k, int num) {
    if (tr[k].ls) pia(tr[k].ls, num);
    p[num + tr[tr[k].ls].sz + 1] = tr[k].p;
    rub[++top] = k;
    if (tr[k].rs) pia(tr[k].rs, num + tr[tr[k].ls].sz + 1);
}

inline void check(int &k, int wd) {
    if (al * tr[k].sz < tr[tr[k].ls].sz || al * tr[k].sz < tr[tr[k].rs].sz) {
        pia(k, 0);
        k = build(1, tr[k].sz, wd);
    }
}

inline void ins(Point now, int &k, int wd) {
    if (!k) {
        k = newNode();
        tr[k].p = now;
        tr[k].ls = tr[k].rs = 0;
        pushup(k);
        return;
    }
    if (tr[k].p.x[wd] < now.x[wd]) ins(now, tr[k].rs, wd ^ 1);
    else ins(now, tr[k].ls, wd ^ 1);
    pushup(k);
    check(k, wd);
}

inline int getdis(Point now, int k) {
    int ret = 0;
    for (int i = 0; i < 2; ++i) {
        ret += max(0, now.x[i] - tr[k].mx[i]) + max(0, tr[k].mi[i] - now.x[i]);
    }
    return ret;
}

inline int dis(Point a, Point b) {
    return abs(a.x[0] - b.x[0]) + abs(a.x[1] - b.x[1]);
}

inline void query(Point now, int k) {
    ans = min(ans, dis(now, tr[k].p));
    int dl = INF, dr = INF;
    if (tr[k].ls) dl = getdis(now, tr[k].ls);
    if (tr[k].rs) dr = getdis(now, tr[k].rs);
    if (dl < dr) {
        if (dl < ans) query(now, tr[k].ls);
        if (dr < ans) query(now, tr[k].rs);
    }
    else {
        if (dr < ans) query(now, tr[k].rs);
        if (dl < ans) query(now, tr[k].ls);
    }
}

int main() {
    int n = read(), m = read();
    for (int i = 1; i <= n; ++i) {
        p[i].x[0] = read();
        p[i].x[1] = read();
    }
    root = build(1, n, 0);
    while(m--) {
        int opt = read(), x = read(), y = read();
        if (opt == 1) ins(Point(x, y), root, 0);
        else ans = INF, query(Point(x, y), root), printf("%d\n", ans);
    }
    return 0;
}
onerror {resume} quietly WaveActivateNextPane {} 0 add wave -noupdate /tb_IBGT_Drive/s_clk add wave -noupdate /tb_IBGT_Drive/s_reset add wave -noupdate /tb_IBGT_Drive/shut_hv_2s add wave -noupdate /tb_IBGT_Drive/error_lamp add wave -noupdate /tb_IBGT_Drive/start_hv add wave -noupdate /tb_IBGT_Drive/starting_hv add wave -noupdate /tb_IBGT_Drive/stage1_hv add wave -noupdate /tb_IBGT_Drive/hvs2_elapsed_2s_q add wave -noupdate /tb_IBGT_Drive/charging_signal add wave -noupdate /tb_IBGT_Drive/sample_signal add wave -noupdate /tb_IBGT_Drive/igbt_drive add wave -noupdate /tb_IBGT_Drive/clk_1ms add wave -noupdate /tb_IBGT_Drive/en add wave -noupdate -color Green /tb_IBGT_Drive/seq_charging_A add wave -noupdate /tb_IBGT_Drive/charging_signal_dbc add wave -noupdate /tb_IBGT_Drive/charging_sensor add wave -noupdate /tb_IBGT_Drive/charging_sensor_dbc add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/tick add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/chg_num add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/chg_interval add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/chg_width add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/chg_on add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/sync_on add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/sync_off add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/dischg_on add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/dischg_off add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/mw_on add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/mw_off add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/counter add wave -noupdate -color Violet /tb_IBGT_Drive/pulse_inst/seq_sync add wave -noupdate -color Violet /tb_IBGT_Drive/pulse_inst/seq_microwave_on add wave -noupdate -color Violet /tb_IBGT_Drive/pulse_inst/seq_charging_A add wave -noupdate -color Violet /tb_IBGT_Drive/pulse_inst/seq_charging_B add wave -noupdate -color Violet /tb_IBGT_Drive/pulse_inst/dischg_choice add wave -noupdate -color Violet /tb_IBGT_Drive/pulse_inst/s_charging add wave -noupdate -color Violet /tb_IBGT_Drive/pulse_inst/s_discharging add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/chg_num_r add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/chg_interval_end add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/chg_width_end add wave -noupdate -color Violet /tb_IBGT_Drive/pulse_inst/s_sync add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/dischg_start add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/dischg_end add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/sample_start add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/sample_end add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/mw_start add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/mw_end add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/sync_start add wave -noupdate -color Violet -radix unsigned /tb_IBGT_Drive/pulse_inst/sync_end add wave -noupdate -color Cyan -radix unsigned /tb_IBGT_Drive/IGBT_DRIVE_inst/max_chg_width add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/charging_signal add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/sample_signal add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/chg_forbidden add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/igbt_drive add wave -noupdate -color Violet /tb_IBGT_Drive/pulse_inst/s_microwave_on add wave -noupdate -color Violet /tb_IBGT_Drive/pulse_inst/seq_discharging_A add wave -noupdate -color Violet /tb_IBGT_Drive/pulse_inst/seq_discharging_B add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/w_2 add wave -noupdate -color Cyan -radix unsigned /tb_IBGT_Drive/IGBT_DRIVE_inst/fall_delay add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/en add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/charging_sensor add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/max_pulse_width add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/rise_cap add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/rise add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/chg_fall_cap add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/fall_cap add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/fall add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/chg_fall add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/ending add wave -noupdate -color Cyan /tb_IBGT_Drive/IGBT_DRIVE_inst/sample add wave -noupdate -color Cyan -radix unsigned /tb_IBGT_Drive/IGBT_DRIVE_inst/mag_cnt add wave -noupdate -color Cyan -radix unsigned /tb_IBGT_Drive/IGBT_DRIVE_inst/sample_forbidden add wave -noupdate -color Cyan -radix unsigned /tb_IBGT_Drive/IGBT_DRIVE_inst/charing_cnt TreeUpdate [SetDefaultTree] WaveRestoreCursors {{Cursor 6} {58675767 ns} 0} quietly wave cursor active 1 configure wave -namecolwidth 299 configure wave -valuecolwidth 100 configure wave -justifyvalue left configure wave -signalnamewidth 0 configure wave -snapdistance 10 configure wave -datasetprefix 0 configure wave -rowmargin 4 configure wave -childrowmargin 2 configure wave -gridoffset 0 configure wave -gridperiod 1 configure wave -griddelta 40 configure wave -timeline 0 configure wave -timelineunits ns update WaveRestoreZoom {35484683 ns} {74949143 ns} 这是在做什么?
07-13
【复现】并_离网风光互补制氢合成氨系统容量-调度优化分析(Python代码实现)内容概要:本文围绕&ldquo;并_离网风光互补制氢合成氨系统容量-调度优化分析&rdquo;的主题,提供了基于Python代码实现的技术研究与复现方法。通过构建风能、太阳能互补的可再生能源系统模型,结合电解水制氢与合成氨工艺流程,对系统的容量配置与运行调度进行联合优化分析。利用优化算法求解系统在不同运行模式下的最优容量配比和调度策略,兼顾经济性、能效性和稳定性,适用于并网与离网两种场景。文中强调通过代码实践完成系统建模、约束设定、目标函数设计及求解过程,帮助读者掌握综合能源系统优化的核心方法。; 适合人群:具备一定Python编程基础和能源系统背景的研究生、科研人员及工程技术人员,尤其适合从事可再生能源、氢能、综合能源系统优化等相关领域的从业者;; 使用场景及目标:①用于教学与科研中对风光制氢合成氨系统的建模与优化训练;②支撑实际项目中对多能互补系统容量规划与调度策略的设计与验证;③帮助理解优化算法在能源系统中的应用逻辑与实现路径;; 阅读建议:建议读者结合文中提供的Python代码进行逐模块调试与运行,配合文档说明深入理解模型构建细节,重点关注目标函数设计、约束条件设置及求解器调用方式,同时可对比Matlab版本实现以拓宽工具应用视野。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值