首页 > 编程语言 >C++ -- 红黑树的基本操作

C++ -- 红黑树的基本操作

时间:2024-06-17 13:57:13浏览次数:13  
标签:node parent -- nullptr C++ color 基本操作 root left

目录

摘要

基本规则

基本操作

利用Graphviz 库

总结


摘要

红黑树是一种自平衡的二叉搜索树,它在插入和删除节点时,通过颜色和旋转操作保持树的平衡,确保插入、删除和查找的时间复杂度都是 (O(log n))。红黑树的每个节点都有一个颜色属性,红色或黑色。通过一些规则,红黑树保持了相对平衡,使得最长路径长度不会超过最短路径长度的两倍。

基本规则

1. 每个节点不是红色就是黑色。
2. 根节点是黑色。
3. 每个叶子节点(NIL节点)是黑色。
4. 如果一个节点是红色的,则它的两个子节点都是黑色的(从每个叶子到根的所有路径上不能有两个连续的红色节点)。
5. 从任一节点到其每个叶子的所有简单路径都包含相同数量的黑色节点。

基本操作

插入操作

#include <iostream>

enum Color { RED, BLACK };

struct Node {
    int data;
    Color color;
    Node *left, *right, *parent;

    Node(int data) : data(data), color(RED), left(nullptr), right(nullptr), parent(nullptr) {}
};

class RedBlackTree {
public:
    RedBlackTree() : root(nullptr) {}

    void insert(int data) {
        Node* newNode = new Node(data);
        root = bstInsert(root, newNode);
        fixViolation(newNode);
    }

    void inorder() { inorderHelper(root); }

private:
    Node* root;

    Node* bstInsert(Node* root, Node* node) {
        if (root == nullptr) return node;
        if (node->data < root->data) {
            root->left = bstInsert(root->left, node);
            root->left->parent = root;
        } else if (node->data > root->data) {
            root->right = bstInsert(root->right, node);
            root->right->parent = root;
        }
        return root;
    }

    void fixViolation(Node* node) {
        Node* parent = nullptr;
        Node* grandParent = nullptr;

        while (node != root && node->color == RED && node->parent->color == RED) {
            parent = node->parent;
            grandParent = parent->parent;

            if (parent == grandParent->left) {
                Node* uncle = grandParent->right;

                if (uncle != nullptr && uncle->color == RED) {
                    grandParent->color = RED;
                    parent->color = BLACK;
                    uncle->color = BLACK;
                    node = grandParent;
                } else {
                    if (node == parent->right) {
                        rotateLeft(parent);
                        node = parent;
                        parent = node->parent;
                    }
                    rotateRight(grandParent);
                    std::swap(parent->color, grandParent->color);
                    node = parent;
                }
            } else {
                Node* uncle = grandParent->left;

                if (uncle != nullptr && uncle->color == RED) {
                    grandParent->color = RED;
                    parent->color = BLACK;
                    uncle->color = BLACK;
                    node = grandParent;
                } else {
                    if (node == parent->left) {
                        rotateRight(parent);
                        node = parent;
                        parent = node->parent;
                    }
                    rotateLeft(grandParent);
                    std::swap(parent->color, grandParent->color);
                    node = parent;
                }
            }
        }
        root->color = BLACK;
    }

    void rotateLeft(Node* node) {
        Node* rightNode = node->right;
        node->right = rightNode->left;

        if (node->right != nullptr) node->right->parent = node;
        rightNode->parent = node->parent;

        if (node->parent == nullptr) root = rightNode;
        else if (node == node->parent->left) node->parent->left = rightNode;
        else node->parent->right = rightNode;

        rightNode->left = node;
        node->parent = rightNode;
    }

    void rotateRight(Node* node) {
        Node* leftNode = node->left;
        node->left = leftNode->right;

        if (node->left != nullptr) node->left->parent = node;
        leftNode->parent = node->parent;

        if (node->parent == nullptr) root = leftNode;
        else if (node == node->parent->left) node->parent->left = leftNode;
        else node->parent->right = leftNode;

        leftNode->right = node;
        node->parent = leftNode;
    }

    void inorderHelper(Node* root) {
        if (root == nullptr) return;
        inorderHelper(root->left);
        std::cout << root->data << " ";
        inorderHelper(root->right);
    }
};

int main() {
    RedBlackTree tree;
    tree.insert(10);
    tree.insert(20);
    tree.insert(30);
    tree.insert(15);

    std::cout << "Inorder traversal of the constructed tree is ";
    tree.inorder();
    std::cout << std::endl;

    return 0;
}
// Output
Inorder traversal of the constructed tree is 10 15 20 30

     20(B)
   /    \
10(B)  30(B)
   \
   15(R)

插入和删除操作

#include <iostream>
#include <queue>

enum Color { RED, BLACK };

struct Node {
    int data;
    Color color;
    Node *left, *right, *parent;

    Node(int data) : data(data), color(RED), left(nullptr), right(nullptr), parent(nullptr) {}

    Node* sibling() {
        if (parent == nullptr) return nullptr;
        return this == parent->left ? parent->right : parent->left;
    }

    bool hasRedChild() {
        return (left != nullptr && left->color == RED) || (right != nullptr && right->color == RED);
    }
};

class RedBlackTree {
public:
    Node* root;

    RedBlackTree() : root(nullptr) {}

    void insert(int data) {
        Node* newNode = new Node(data);
        root = bstInsert(root, newNode);
        fixViolation(newNode);
    }

    void deleteNode(int data) {
        Node* nodeToDelete = search(root, data);
        if (nodeToDelete == nullptr) return;
        deleteBSTNode(nodeToDelete);
    }

    void inorder() { inorderHelper(root); }

    void levelOrder() {
        if (root == nullptr) return;
        std::queue<Node*> q;
        q.push(root);

        while (!q.empty()) {
            Node* temp = q.front();
            std::cout << temp->data << " ";
            q.pop();

            if (temp->left != nullptr)
                q.push(temp->left);

            if (temp->right != nullptr)
                q.push(temp->right);
        }
    }

private:
    Node* bstInsert(Node* root, Node* node) {
        if (root == nullptr) return node;
        if (node->data < root->data) {
            root->left = bstInsert(root->left, node);
            root->left->parent = root;
        } else if (node->data > root->data) {
            root->right = bstInsert(root->right, node);
            root->right->parent = root;
        }
        return root;
    }

    Node* search(Node* root, int data) {
        if (root == nullptr || root->data == data) return root;
        return data < root->data ? search(root->left, data) : search(root->right, data);
    }

    void deleteBSTNode(Node* node) {
        Node* replacement = BSTreplace(node);
        bool bothBlack = ((replacement == nullptr || replacement->color == BLACK) && (node->color == BLACK));
        Node* parent = node->parent;

        if (replacement == nullptr) {
            if (node == root) {
                root = nullptr;
            } else {
                if (bothBlack) {
                    fixDoubleBlack(node);
                } else {
                    if (node->sibling() != nullptr) node->sibling()->color = RED;
                }
                if (node == node->parent->left) {
                    node->parent->left = nullptr;
                } else {
                    node->parent->right = nullptr;
                }
            }
            delete node;
            return;
        }

        if (node->left == nullptr || node->right == nullptr) {
            if (node == root) {
                node->data = replacement->data;
                node->left = node->right = nullptr;
                delete replacement;
            } else {
                if (node == node->parent->left) {
                    parent->left = replacement;
                } else {
                    parent->right = replacement;
                }
                delete node;
                replacement->parent = parent;
                if (bothBlack) {
                    fixDoubleBlack(replacement);
                } else {
                    replacement->color = BLACK;
                }
            }
            return;
        }

        std::swap(node->data, replacement->data);
        deleteBSTNode(replacement);
    }

    Node* BSTreplace(Node* node) {
        if (node->left != nullptr && node->right != nullptr) return successor(node->right);
        if (node->left == nullptr && node->right == nullptr) return nullptr;
        return node->left != nullptr ? node->left : node->right;
    }

    Node* successor(Node* node) {
        Node* temp = node;
        while (temp->left != nullptr) temp = temp->left;
        return temp;
    }

    void fixViolation(Node* node) {
        Node* parent = nullptr;
        Node* grandParent = nullptr;

        while (node != root && node->color == RED && node->parent->color == RED) {
            parent = node->parent;
            grandParent = parent->parent;

            if (parent == grandParent->left) {
                Node* uncle = grandParent->right;

                if (uncle != nullptr && uncle->color == RED) {
                    grandParent->color = RED;
                    parent->color = BLACK;
                    uncle->color = BLACK;
                    node = grandParent;
                } else {
                    if (node == parent->right) {
                        rotateLeft(parent);
                        node = parent;
                        parent = node->parent;
                    }
                    rotateRight(grandParent);
                    std::swap(parent->color, grandParent->color);
                    node = parent;
                }
            } else {
                Node* uncle = grandParent->left;

                if (uncle != nullptr && uncle->color == RED) {
                    grandParent->color = RED;
                    parent->color = BLACK;
                    uncle->color = BLACK;
                    node = grandParent;
                } else {
                    if (node == parent->left) {
                        rotateRight(parent);
                        node = parent;
                        parent = node->parent;
                    }
                    rotateLeft(grandParent);
                    std::swap(parent->color, grandParent->color);
                    node = parent;
                }
            }
        }
        root->color = BLACK;
    }

    void fixDoubleBlack(Node* node) {
        if (node == root) return;

        Node* sibling = node->sibling();
        Node* parent = node->parent;
        if (sibling == nullptr) {
            fixDoubleBlack(parent);
        } else {
            if (sibling->color == RED) {
                parent->color = RED;
                sibling->color = BLACK;
                if (sibling == parent->left) {
                    rotateRight(parent);
                } else {
                    rotateLeft(parent);
                }
                fixDoubleBlack(node);
            } else {
                if (sibling->hasRedChild()) {
                    if (sibling->left != nullptr && sibling->left->color == RED) {
                        if (sibling == parent->left) {
                            sibling->left->color = sibling->color;
                            sibling->color = parent->color;
                            rotateRight(parent);
                        } else {
                            sibling->left->color = parent->color;
                            rotateRight(sibling);
                            rotateLeft(parent);
                        }
                    } else {
                        if (sibling == parent->left) {
                            sibling->right->color = parent->color;
                            rotateLeft(sibling);
                            rotateRight(parent);
                        } else {
                            sibling->right->color = sibling->color;
                            sibling->color = parent->color;
                            rotateLeft(parent);
                        }
                    }
                    parent->color = BLACK;
                } else {
                    sibling->color = RED;
                    if (parent->color == BLACK) {
                        fixDoubleBlack(parent);
                    } else {
                        parent->color = BLACK;
                    }
                }
            }
        }
    }

    void rotateLeft(Node* node) {
        Node* rightNode = node->right;
        node->right = rightNode->left;

        if (node->right != nullptr) node->right->parent = node;
        rightNode->parent = node->parent;

        if (node->parent == nullptr) root = rightNode;
        else if (node == node->parent->left) node->parent->left = rightNode;
        else node->parent->right = rightNode;

        rightNode->left = node;
        node->parent = rightNode;
    }

    void rotateRight(Node* node) {
        Node* leftNode = node->left;
        node->left = leftNode->right;

        if (node->left != nullptr) node->left->parent = node;
        leftNode->parent = node->parent;

        if (node->parent == nullptr) root = leftNode;
        else if (node == node->parent->left) node->parent->left = leftNode;
        else node->parent->right = leftNode;

        leftNode->right = node;
        node->parent = leftNode;
    }

    void inorderHelper(Node* root) {
        if (root == nullptr) return;
        inorderHelper(root->left);
        std::cout << root->data << " ";
        inorderHelper(root->right);
    }
};

int main() {
    RedBlackTree tree;
    tree.insert(10);
    tree.insert(20);
    tree.insert(30);
    tree.insert(15);
    tree.insert(25);
    tree.insert(5);

    std::cout << "Inorder traversal of the constructed tree is ";
    tree.inorder();
    std::cout << std::endl;

    tree.deleteNode(20);

    std::cout << "Inorder traversal after deleting 20 is ";
    tree.inorder();
    std::cout << std::endl;

    std::cout << "Level order traversal of the tree is ";
    tree.levelOrder();
    std::cout << std::endl;

    return 0;
}
// Output

Inorder traversal of the constructed tree is 5 10 15 20 25 30 
Inorder traversal after deleting 20 is 5 10 15 25 30 
Level order traversal of the tree is 15 10 30 5 25 


     15(B)
   /    \
10(B)  30(B)
 /     /
5(B)  25(R)

利用Graphviz 库

利用 Graphviz 库的图形化表示我们需要生成的红黑树。

Graphviz Online

#include <iostream>
#include <fstream>
#include <queue>

enum Color { RED, BLACK };

struct Node {
    int data;
    Color color;
    Node *left, *right, *parent;

    Node(int data) : data(data), color(RED), left(nullptr), right(nullptr), parent(nullptr) {}

    Node* sibling() {
        if (parent == nullptr) return nullptr;
        return this == parent->left ? parent->right : parent->left;
    }

    bool hasRedChild() {
        return (left != nullptr && left->color == RED) || (right != nullptr && right->color == RED);
    }
};

class RedBlackTree {
public:
    Node* root;

    RedBlackTree() : root(nullptr) {}

    void insert(int data) {
        Node* newNode = new Node(data);
        root = bstInsert(root, newNode);
        fixViolation(newNode);
    }

    void deleteNode(int data) {
        Node* nodeToDelete = search(root, data);
        if (nodeToDelete == nullptr) return;
        deleteBSTNode(nodeToDelete);
    }

    void inorder() { inorderHelper(root); }

    void levelOrder() {
        if (root == nullptr) return;
        std::queue<Node*> q;
        q.push(root);

        while (!q.empty()) {
            Node* temp = q.front();
            std::cout << temp->data << " ";
            q.pop();

            if (temp->left != nullptr)
                q.push(temp->left);

            if (temp->right != nullptr)
                q.push(temp->right);
        }
    }

    void generateGraphviz(const std::string& filename) {
        std::ofstream file(filename);
        file << "digraph G {\n";
        if (root == nullptr) {
            file << "}\n";
            return;
        }
        generateGraphvizHelper(file, root);
        file << "}\n";
    }

private:
    Node* bstInsert(Node* root, Node* node) {
        if (root == nullptr) return node;
        if (node->data < root->data) {
            root->left = bstInsert(root->left, node);
            root->left->parent = root;
        } else if (node->data > root->data) {
            root->right = bstInsert(root->right, node);
            root->right->parent = root;
        }
        return root;
    }

    Node* search(Node* root, int data) {
        if (root == nullptr || root->data == data) return root;
        return data < root->data ? search(root->left, data) : search(root->right, data);
    }

    void deleteBSTNode(Node* node) {
        Node* replacement = BSTreplace(node);
        bool bothBlack = ((replacement == nullptr || replacement->color == BLACK) && (node->color == BLACK));
        Node* parent = node->parent;

        if (replacement == nullptr) {
            if (node == root) {
                root = nullptr;
            } else {
                if (bothBlack) {
                    fixDoubleBlack(node);
                } else {
                    if (node->sibling() != nullptr) node->sibling()->color = RED;
                }
                if (node == node->parent->left) {
                    node->parent->left = nullptr;
                } else {
                    node->parent->right = nullptr;
                }
            }
            delete node;
            return;
        }

        if (node->left == nullptr || node->right == nullptr) {
            if (node == root) {
                node->data = replacement->data;
                node->left = node->right = nullptr;
                delete replacement;
            } else {
                if (node == node->parent->left) {
                    parent->left = replacement;
                } else {
                    parent->right = replacement;
                }
                delete node;
                replacement->parent = parent;
                if (bothBlack) {
                    fixDoubleBlack(replacement);
                } else {
                    replacement->color = BLACK;
                }
            }
            return;
        }

        std::swap(node->data, replacement->data);
        deleteBSTNode(replacement);
    }

    Node* BSTreplace(Node* node) {
        if (node->left != nullptr && node->right != nullptr) return successor(node->right);
        if (node->left == nullptr && node->right == nullptr) return nullptr;
        return node->left != nullptr ? node->left : node->right;
    }

    Node* successor(Node* node) {
        Node* temp = node;
        while (temp->left != nullptr) temp = temp->left;
        return temp;
    }

    void fixViolation(Node* node) {
        Node* parent = nullptr;
        Node* grandParent = nullptr;

        while (node != root && node->color == RED && node->parent->color == RED) {
            parent = node->parent;
            grandParent = parent->parent;

            if (parent == grandParent->left) {
                Node* uncle = grandParent->right;

                if (uncle != nullptr && uncle->color == RED) {
                    grandParent->color = RED;
                    parent->color = BLACK;
                    uncle->color = BLACK;
                    node = grandParent;
                } else {
                    if (node == parent->right) {
                        rotateLeft(parent);
                        node = parent;
                        parent = node->parent;
                    }
                    rotateRight(grandParent);
                    std::swap(parent->color, grandParent->color);
                    node = parent;
                }
            } else {
                Node* uncle = grandParent->left;

                if (uncle != nullptr && uncle->color == RED) {
                    grandParent->color = RED;
                    parent->color = BLACK;
                    uncle->color = BLACK;
                    node = grandParent;
                } else {
                    if (node == parent->left) {
                        rotateRight(parent);
                        node = parent;
                        parent = node->parent;
                    }
                    rotateLeft(grandParent);
                    std::swap(parent->color, grandParent->color);
                    node = parent;
                }
            }
        }
        root->color = BLACK;
    }

    void fixDoubleBlack(Node* node) {
        if (node == root) return;

        Node* sibling = node->sibling();
        Node* parent = node->parent;
        if (sibling == nullptr) {
            fixDoubleBlack(parent);
        } else {
            if (sibling->color == RED) {
                parent->color = RED;
                sibling->color = BLACK;
                if (sibling == parent->left) {
                    rotateRight(parent);
                } else {
                    rotateLeft(parent);
                }
                fixDoubleBlack(node);
            } else {
                if (sibling->hasRedChild()) {
                    if (sibling->left != nullptr && sibling->left->color == RED) {
                        if (sibling == parent->left) {
                            sibling->left->color = sibling->color;
                            sibling->color = parent->color;
                            rotateRight(parent);
                        } else {
                            sibling->left->color = parent->color;
                            rotateRight(sibling);
                            rotateLeft(parent);
                        }
                    } else {
                        if (sibling == parent->left) {
                            sibling->right->color = parent->color;
                            rotateLeft(sibling);
                            rotateRight(parent);
                        } else {
                            sibling->right->color = sibling->color;
                            sibling->color = parent->color;
                            rotateLeft(parent);
                        }
                    }
                    parent->color = BLACK;
                } else {
                    sibling->color = RED;
                    if (parent->color == BLACK) {
                        fixDoubleBlack(parent);
                    } else {
                        parent->color = BLACK;
                    }
                }
            }
        }
    }

    void rotateLeft(Node* node) {
        Node* rightNode = node->right;
        node->right = rightNode->left;

        if (node->right != nullptr) node->right->parent = node;
        rightNode->parent = node->parent;

        if (node->parent == nullptr) root = rightNode;
        else if (node == node->parent->left) node->parent->left = rightNode;
        else node->parent->right = rightNode;

        rightNode->left = node;
        node->parent = rightNode;
    }

    void rotateRight(Node* node) {
        Node* leftNode = node->left;
        node->left = leftNode->right;

        if (node->left != nullptr) node->left->parent = node;
        leftNode->parent = node->parent;

        if (node->parent == nullptr) root = leftNode;
        else if (node == node->parent->left) node->parent->left = leftNode;
        else node->parent->right = leftNode;

        leftNode->right = node;
        node->parent = leftNode;
    }

    void inorderHelper(Node* root) {
        if (root == nullptr) return;
        inorderHelper(root->left);
        std::cout << root->data << " ";
        inorderHelper(root->right);
    }

    void generateGraphvizHelper(std::ofstream& file, Node* root) {
        if (root->left != nullptr) {
            file << root->data << " -> " << root->left->data << ";\n";
            generateGraphvizHelper(file, root->left);
        } else {
            file << "null" << root->data << "L [shape=point];\n";
            file << root->data << " -> null" << root->data << "L;\n";
        }

        if (root->right != nullptr) {
            file << root->data << " -> " << root->right->data << ";\n";
            generateGraphvizHelper(file, root->right);
        } else {
            file << "null" << root->data << "R [shape=point];\n";
            file << root->data << " -> null" << root->data << "R;\n";
        }
    }
};

int main() {
    RedBlackTree tree;
    tree.insert(10);
    tree.insert(20);
    tree.insert(30);
    tree.insert(15);
    tree.insert(25);
    tree.insert(5);

    tree.generateGraphviz("rbtree.dot");

    std::cout << "Graphviz dot file generated as rbtree.dot" << std::endl;

    return 0;
}
// Output
digraph G {
10 -> 5;
10 -> 20;
20 -> 15;
20 -> 30;
30 -> 25;
null5L [shape=point];
5 -> null5L;
null5R [shape=point];
5 -> null5R;
null15L [shape=point];
15 -> null15L;
null15R [shape=point];
15 -> null15R;
null25L [shape=point];
25 -> null25L;
null25R [shape=point];
25 -> null25R;
null30L [shape=point];
30 -> null30L;
null30R [shape=point];
30 -> null30R;
}

  10
 /  \
5    20
    /  \
   15  30
       /
      25

总结

红黑树(Red-Black Tree)是一种自平衡二叉搜索树,常用于需要高效插入、删除和查找操作的数据结构中。红黑树的特点包括每个节点是红色或黑色、根节点是黑色、红色节点的子节点必须是黑色、从任一节点到其每个叶子节点的路径上的黑色节点数目相同。

标签:node,parent,--,nullptr,C++,color,基本操作,root,left
From: https://blog.csdn.net/GOLOJO/article/details/139741796

相关文章

  • 11大3D模型销售网站
     无法决定是在在线市场上销售3D模型还是在电子商务平台上销售?让我们帮助你。在这篇博文中,我们列出了10个在线销售3D模型的最佳网站。我们还列出了每个平台的优缺点,以便你做出明智的决定。那么,让我们开始吧!1、SellfySellfy是一种易于使用的电子商务解决方案,具有大......
  • 科技政策查询(五一极限)
    验收通过了,因为要赶车所以当场学习能力大爆发了,成功验收,也成功赶上了车。Control层packagecom.cxk.baseframe.project.systemmanage.controller;importjava.util.List;importjava.util.Map;importjavax.servlet.http.HttpServletResponse;importjavax.annotation.Resource;......
  • MYSQL查询语句报1 of ORDER BY clause is not in SELECT list
    我的语句如下:SELECTDISTINCT r.id, r.device_model_id, r.device_model_name, r.alarm_type_id, r.alarm_type_name, r.alarm_level, r.filter_condition, r.filter_condition_value, r.offline_tag, p.param_data_id, p.parmsFROM alarm_ruler, alarm_rule_pa......
  • LeetCode 2340. Minimum Adjacent Swaps to Make a Valid Array
    原题链接在这里:https://leetcode.com/problems/minimum-adjacent-swaps-to-make-a-valid-array/description/题目:Youaregivena 0-indexed integerarray nums.Swaps of adjacent elementsareabletobeperformedon nums.A valid arraymeetsthefollowingco......
  • iOS开发之弹窗管理
    前言“千淘万漉虽辛苦,吹尽狂沙始到金。”在这快速变化的互联网行业,身边的朋友有的选择了勇敢创业,有的则在技术的海洋中默默耕耘。时常在深夜反思,作为一个开发者,我们的价值何在?答案或许就在那行代码中,润物细无声。以下是我在日常开发中封装的一个弹窗管理工具——CLPopoverManager......
  • 椭圆曲线加密算法中公钥与私钥互换性分析
    PrimiHub一款由密码学专家团队打造的开源隐私计算平台,专注于分享数据安全、密码学、联邦学习、同态加密等隐私计算领域的技术和内容。在现代密码学中,椭圆曲线加密算法(EllipticCurveCryptography,ECC)因其高效的加密速度、较小的密钥尺寸和较高的安全性而受到广泛关注。ECC基......
  • MySQL 5.7 安装教程(Win 10)
    转自:https://www.cnblogs.com/swjian/p/11907600.htmlMySQL5.7下载官网下载(不推荐使用):https://dev.mysql.com/downloads/mysql/清华镜像站下载(推荐):https://mirrors.tuna.tsinghua.edu.cn/mysql/downloads/MySQL-5.7/mysql-5.7.27-winx64.zipMySQL5.7解压将下载完的zi......
  • three.js 从零学习
    基本概念场景用来呈现内容的容器我理解就是类似canvas相机记录场景中呈现的内容一般分类两大类1.正投影相机  所有内容同等大小呈现处理2.透视相机 符合人眼逻辑近大远小渲染器决定场......
  • 【递归、搜索与回溯】综合练习二
    综合练习二1.组合2.目标和3.组合总和4.字母大小写全排列点赞......
  • D - Souvenirs
    D-Souvenirshttps://atcoder.jp/contests/abc358/tasks/abc358_d 思路贪心算法。把a数组和b数组从小到大排序。遍历b数组的每一个元素bi,在a数组中找到第一个大于等于bi元素,累加值。 Codehttps://atcoder.jp/contests/abc358/submissions/54656383#defineintlong......