Skip to content

12111: 【原2111】最小差值

题目

题目描述

author: ftiasch 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/2111

Description

维护集合\( S\),初始时为空集,支持\( 3\)种操作:

询问\( |x - a|\)的最小值,其中\( x \in S\)

插入元素 \( x\)

删除元素 \( x\)

Input Format

第\(1\)行,\(1\)个整数\(M\),表示操作的数量。

接下来\(M\)行,每行描述一个操作,共有\(3\)种类型:

0 x, 询问要求的最小值

1 x, 插入元素\( x\)

2 x, 删除元素\( x\)

Output Format

对于每个询问,输出对应的最小值。

Sample Input

5
1 0
1 1
0 2
2 1
0 2

Sample Output

1
2

Specification

对于\(30\%\)的数据,\(1 \leq M \leq 1000\)。

对于\(100\%\)的数据,\(1 \leq M \leq 10^5, 0 \leq x \leq 10^8\)。保证不会插入重复的元素,不会删除不存在的元素,查询时集合至少有\(1\)个元素。

ligongzzz's solution

#include "iostream"
#include "cstdio"
#include "cmath"
#include "set"
#include "algorithm"
using namespace std;

int main() {
    set<int> setdata;
    int M;
    cin >> M;

    for (; M > 0; --M) {
        int op, x;
        scanf("%d %d", &op, &x);

        if (op == 0) {
            auto p=setdata.lower_bound(x);
            if (p == setdata.end())
                printf("%d\n", (int)abs(*setdata.rbegin() - x));
            else if (p == setdata.begin())
                printf("%d\n", (int)abs(*setdata.begin() - x));
            else {
                int x1 = (int)abs(*p - x),
                    x2 = (int)abs(*(--p) - x);
                printf("%d\n", min(x1, x2));
            }

        }
        else if (op == 1) {
            setdata.insert(x);
        }
        else {
            setdata.erase(setdata.find(x));
        }
    }
    return 0;
}

Neight99's solution

#include <cstring>
#include <iostream>

using namespace std;

int min(int a, int b) { return (a > b) ? b : a; }

class BinarySearchTree {
   private:
    struct Node {
        int data;
        Node *left;
        Node *right;

        Node(int x = 0, Node *l = 0, Node *r = 0)
            : data(x), left(l), right(r) {}
    };

    int sum;
    Node *root;
    void insert(int x, Node *&rht);
    void deleteNode(int x, Node *&rht);
    void deleteEqual(int x, Node *&rht);
    void find(int x, Node *&rht);
    void clear(Node *&rht);

   public:
    BinarySearchTree();
    ~BinarySearchTree();
    void insert(int x);
    void deleteEqual(int x);
    void find(int x);
    void findIth(int i);
    int findMin(int x);
};

BinarySearchTree::BinarySearchTree() : root(0), sum(0) {}

BinarySearchTree::~BinarySearchTree() { clear(root); }

void BinarySearchTree::clear(Node *&rht) {
    if (rht == 0) {
        return;
    }
    clear(rht->left);
    clear(rht->right);
    delete rht;
    sum--;
}

void BinarySearchTree::insert(int x) { insert(x, root); }

void BinarySearchTree::insert(int x, Node *&rht) {
    if (rht == 0) {
        rht = new Node(x);
        sum++;
    } else if (x < rht->data) {
        insert(x, rht->left);
    } else {
        insert(x, rht->right);
    }
}

void BinarySearchTree::deleteNode(int x, Node *&rhs) {
    if (rhs == 0) {
        return;
    }
    if (x < rhs->data) {
        deleteNode(x, rhs->left);
    } else if (x > rhs->data) {
        deleteNode(x, rhs->right);
    } else if (rhs->left != 0 && rhs->right != 0) {
        Node *p = rhs->right;
        while (p->left != 0) {
            p = p->left;
        }
        rhs->data = p->data;
        deleteNode(rhs->data, rhs->right);
    } else {
        Node *clean = rhs;
        rhs = (rhs->left != 0) ? rhs->left : rhs->right;
        delete clean;
        sum--;
    }
}

void BinarySearchTree::deleteEqual(int x) { deleteEqual(x, root); }

void BinarySearchTree::deleteEqual(int x, Node *&rht) {
    deleteNode(x, root);
    if (sum == 0) {
        root = NULL;
    }
}

void BinarySearchTree::find(int x) { find(x, root); }

void BinarySearchTree::find(int x, Node *&rht) {
    if (rht == 0) {
        cout << "N\n";
    } else if (x == rht->data) {
        cout << "Y\n";
    } else if (x < rht->data) {
        find(x, rht->left);
    } else {
        find(x, rht->right);
    }
}

int BinarySearchTree::findMin(int x) {
    int ans = 2147483646;
    int p;
    Node *n = root;

    while (n != 0) {
        if (x < n->data) {
            ans = min((n->data - x), ans);
            n = n->left;
        } else if (x > n->data) {
            ans = min((x - n->data), ans);
            n = n->right;
        } else {
            return 0;
        }
    }

    return ans;
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int n, order;
    int x;
    BinarySearchTree bst;

    cin >> n;
    for (int i = 0; i < n; i++) {
        cin >> order >> x;
        switch (order) {
            case 0:
                cout << bst.findMin(x) << '\n';
                break;
            case 1:
                bst.insert(x);
                break;
            case 2:
                bst.deleteEqual(x);
                break;
        }
    }

    return 0;
}

q4x3's solution

/**
 * 二叉搜索树
 **/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>

struct node {
    int data;
    node *left, *right;
    node(int dt):data(dt), left(nullptr), right(nullptr) {}
};

void insert(node* &rt, int p) {
    if(rt == nullptr) {
        rt = new node(p);
    } else if(rt->data < p) {
        insert(rt->right, p);
    } else if(rt->data > p) {
        insert(rt->left, p);
    }
}

void del(node* &rt, int key) {
    if(rt->data < key) {
        del(rt->right, key);
        return;
    } else if(rt->data > key) {
        del(rt->left, key);
        return;
    }
    if(rt->left == nullptr && rt->right == nullptr) {
        delete rt;
        rt = nullptr;
    } else if(rt->left && rt->right == nullptr) {
        rt = rt->left;
    } else if(rt->left == nullptr && rt->right) {
        rt = rt->right;
    } else {
        node* tmp = rt->right;
        while(tmp->left) tmp = tmp->left;
        rt->data = tmp->data;
        del(rt->right, rt->data);
    }
}

int min(int x, int y) {
    return x < y ? x : y;
}

int query(node* rt, int x) {
    int ans = 2e9;
    while(rt != nullptr) {
        if(rt->data < x) {
            ans = min(ans, x - rt->data);
            rt = rt->right;
        } else if(rt->data > x) {
            ans = min(ans, rt->data - x);
            rt = rt->left;
        } else return 0;
    }
    return ans;
}

node *root;
int M, op, x;

int main() {
    scanf("%d", &M);
    for(int i = 0;i < M;++ i) {
        scanf("%d%d", &op, &x);
        if(op == 0) {
            printf("%d\n", query(root, x));
        } else if(op == 1) {
            insert(root, x);
        } else {
            del(root, x);
        }
    }
}

victrid's solution

#include <cstdio>
#include <iostream>
using namespace std;
#include <cmath>
template <typename T>
class AVL {
protected:
    struct node {
        node* left;
        node* right;
        int height;
        T value;
    };
    node* data;
    size_t __size;
    node* i_query(node* root, T& to_query) {
        if (root == nullptr)
            return nullptr;
        if (root->value == to_query)
            return root;
        if (root->value > to_query) {
            return i_query(root->left, to_query);
        }
        if (root->value < to_query) {
            return i_query(root->right, to_query);
        }
    }
    void setrootheight(node* root) {
        if (root == nullptr)
            return;
        root->height = max((root->left == nullptr ? 0 : root->left->height), (root->right == nullptr ? 0 : root->right->height)) + 1;
    }

    node* right_rotate(node*& root) {
        node* nl   = root->left;
        root->left = nl->right;
        nl->right  = root;
        root       = nl;
        setrootheight(root->left);
        setrootheight(root->right);
        setrootheight(root);
        return root;
    }

    node* left_rotate(node*& root) {
        node* nr    = root->right;
        root->right = nr->left;
        nr->left    = root;
        root        = nr;
        setrootheight(root->left);
        setrootheight(root->right);
        setrootheight(root);
        return root;
    }

    inline int getfactor(node*& root) {
        if (root == nullptr)
            return 0;
        return (root->left == nullptr ? 0 : root->left->height) - (root->right == nullptr ? 0 : root->right->height);
    }

    int balance(node*& root) {
        if (root == nullptr)
            return 0;
        setrootheight(root->left);
        setrootheight(root->right);
        setrootheight(root);
        while (abs(getfactor(root->left)) > 1) {
            balance(root->left);
            setrootheight(root->left);
            setrootheight(root);
        }
        while (abs(getfactor(root->right)) > 1) {
            balance(root->right);
            setrootheight(root->right);
            setrootheight(root);
        }
        int p = getfactor(root);
        if (abs(p) <= 1)
            return 0;
        if (p > 0) {
            if (getfactor(root->left) == 1) {
                right_rotate(root);
                return 0;
            } else {
                left_rotate(root->left);
                right_rotate(root);
                return 0;
            }
        } else {
            if (getfactor(root->right) == -1) {
                left_rotate(root);
                return 0;
            } else {
                right_rotate(root->right);
                left_rotate(root);
                return 0;
            }
        }
    }

    int insert(node*& root, T& to_insert) {
        if (root == nullptr) {
            root = new node{nullptr, nullptr, 1, to_insert};
            __size++;
            return 0;
        }
        if (root->value < to_insert)
            insert(root->right, to_insert);
        else
            insert(root->left, to_insert);
        balance(root);
        return 0;
    }

    node* erasemin(node*& root) {
        if (root == nullptr)
            return nullptr;
        node* to_erase;
        if (root->left == nullptr) {
            to_erase = root;
            root     = root->right;
        } else {
            return erasemin(root->left);
        }
        balance(root);
        return to_erase;
    }

    int erase(node*& root, T& to_delete) {
        if (root == nullptr)
            return -1;
        if (root->value < to_delete)
            erase(root->right, to_delete);
        else if (root->value > to_delete)
            erase(root->left, to_delete);
        else if (root->value == to_delete) {
            __size--;
            node* rr = root;
            if (root->right == nullptr && root->left == nullptr) {
                root = nullptr;
            } else if (root->right == nullptr) {
                root = root->left;
            } else if (root->left == nullptr) {
                root = root->right;
            } else {
                node*& pp   = root->right;
                node* bl    = root->left;
                root        = erasemin(root->right);
                root->right = pp;
                root->left  = bl;
            }
            delete rr;
        }
        balance(root);
        return 0;
    }

public:
    AVL() : data(nullptr), __size(0){};
    int insert(T dat) {
        if (i_query(data, dat) != nullptr)
            return -1;
        else {
            insert(data, dat);
            return 0;
        }
    }
    int find(T dat) {
        return (i_query(data, dat) != nullptr);
    }
    int erase(T dat) {
        if (i_query(data, dat) == nullptr)
            return -1;
        else {
            erase(data, dat);
            return 0;
        }
    }
    int size() {
        return __size;
    }
};
int main() {
    class tr : public AVL<int> {
    protected:
        node* i_qy(node* root, int& to_query, int& valuemin) {
            if (root == nullptr)
                return nullptr;
            if (root->value == to_query) {
                valuemin = 0;
                return root;
            }
            if (root->value > to_query) {
                if (root->value - to_query < valuemin)
                    valuemin = root->value - to_query;
                return i_qy(root->left, to_query, valuemin);
            }
            if (root->value < to_query) {
                if (to_query - root->value < valuemin)
                    valuemin = to_query - root->value;
                return i_qy(root->right, to_query, valuemin);
            }
            return nullptr;
        }

    public:
        int query(int& val) {
            int valuemin = abs(val - data->value);
            i_qy(data, val, valuemin);
            return valuemin;
        }
    } tree;
    int M, a, b;
    scanf("%d", &M);
    while (M--) {
        scanf("%d%d", &a, &b);
        switch (a) {
        case 1:
            tree.insert(b);
            break;
        case 2:
            tree.erase(b);
            break;
        case 0:
            printf("%d\n", tree.query(b));
            break;
        }
    }
    return 0;
}