P2642 双子序列最大和

给定一个整数序列,需要找到两个不相交的连续子序列,使它们的和最大。子序列长度至少为1,且至少间隔一个数。需要处理包含负数的情况,并考虑边界条件。

题目描述

给定一个长度为n的整数序列,要求从中选出两个连续子序列,使得这两个连续子序列的序列和之和最大,最终只需输出最大和。一个连续子序列的和为该子序列中所有数之和。每个连续子序列的最小长度为1,并且两个连续子序列之间至少间隔一个数。

输入输出格式

输入格式:

第一行是一个整数表示n。

第二行是n个整数表示整数序列。

输出格式:

一个数,两个连续子序列的序列和之和。

输入输出样例

输入样例#1:

5
83 223 -13 1331 -935

输出样例#1:

1637

输入样例#2:

3
83 223 -13

输出样例#2:

70

说明

对于30%的数据N<=100。

对于60%的数据有N<=10000。

对于100%的数据有N<=1000000。

数据保证运算过程不会超过long long(int64)。

———————————————————————————————————————

解题思路

首先根据Luogu《P1115 最大子段和》可以知道我们可以求出一直到第i为的当前连续子串和和当前连续子串的最大和,只不过对于这道题我们必须记录每一个点之前(或之后)当前连续子串的最大长度。
我们分别把从左到右的以

题目描述 RB(红黑)树除了是一个二叉搜索树之外,还满足下面规则: 1)每个结点要么是红的,要么是黑的。 2)根结点是黑的。 3)每个叶结点,即空结点是黑的。 4)如果一个结点是红的,那么它的俩个儿子都是黑的。 5)对每个结点,从该结点到其子孙结点的所有路径上包含相同数目的黑结点。 在给定插入序列的情况下,创建RB树,并输出最大值、最小值。 使用c++ 输入格式: 对于每种情况,第一行包含一个正整数N(<=20)。后边为N个不同的整数值,每个整数值以空格隔开。 第二行为要删除的节点个数M,后边为M个不同的整数值,以空格隔开。 输出格式: 第一行为RB树的前序遍历序列,以空格隔开,其中节点值后使用(B)和(R)表示节点的颜色; 第二行为RB树的最大值,最小值,以空格隔开; 第三行为删除M个节点之后的RB树的前序遍历序列,以空格隔开,若树为空,则输出Null; 样例输入1: 13 1 45 34 98 9 4 35 23 36 37 90 85 80 3 85 27 9 样例输出1: 34(B) 4(B) 1(B) 9(B) 23(R) 45(B) 36(B) 35(R) 37(R) 90(R) 85(B) 80(R) 98(B) 1 98 34(B) 4(B) 1(B) 23(B) 45(B) 36(B) 35(R) 37(R) 90(R) 80(B) 98(B) 样例输入2: 3 18 2 7 0 样例输出2: 7(B) 2(R) 18(R) 2 18 7(B) 2(R) 18(R) 注意:遍历输出最后一个结点有空格。删除带有双子结点时,找直接后继。 样例输入输出 样例1 输入: 13 1 45 34 98 9 4 35 23 36 37 90 85 80 3 85 27 9 输出: 34(B) 4(B) 1(B) 9(B) 23(R) 45(B) 36(B) 35(R) 37(R) 90(R) 85(B) 80(R) 98(B) 1 98 34(B) 4(B) 1(B) 23(B) 45(B) 36(B) 35(R) 37(R) 90(R) 80(B) 98(B) 样例2 输入: 3 18 2 7 0 输出: 7(B) 2(R) 18(R) 2 18 7(B) 2(R) 18(R)
最新发布
12-29
# 题目重述 根据给定的插入序列构建红黑树,执行插入与删除操作后,输出以下内容: 1. 构建完成后红黑树的前序遍历结果,每个节点后标注颜色(B为黑,R为红); 2. 树中最小值和最大值; 3. 删除指定节点后的前序遍历结果,若树为空则输出 Null。 --- # 详解 本题要求实现一个完整的红黑树结构,包含插入、删除、旋转及颜色调整等操作,并支持前序遍历、查找最大/最小值等功能。 ### 步骤分析: 1. **红黑树性质维护**: - 每个节点是红色或黑色。 - 根节点为黑色。 - 叶子(NULL)视为黑色。 - 红色节点的子节点必须都是黑色。 - 从任一节点到其所有后代叶子路径上的黑节点数相同(黑高一致)。 2. **插入操作**: - 使用二叉搜索树规则插入新节点,初始颜色设为红色。 - 若破坏了红黑性质(如父节点也为红),通过变色和旋转修复。 3. **删除操作**: - 类似于普通二叉搜索树删除,但需考虑颜色平衡。 - 当删除黑色节点时可能破坏黑高性质,需要通过兄弟节点调整(变色、旋转)来修复。 4. **最大值与最小值查找**: - 最小值:从根开始一直向左直到空。 - 最大值:从根开始一直向右直到空。 5. **前序遍历输出格式化**: - 输出节点值 + (B)/(R),注意最后一个也有空格(按样例要求)。 6. **删除双子节点的情况**: - 使用“直接后继”替换被删节点(即右子树中的最小值)。 7. **输入输出处理**: - 第一行读取 N 和 N 个整数进行插入。 - 第二行读取 M 和 M 个要删除的值。 --- ```cpp #include <iostream> #include <vector> using namespace std; enum Color { RED, BLACK }; struct Node { int data; Color color; Node *left, *right, *parent; Node(int value) : data(value), color(RED), left(nullptr), right(nullptr), parent(nullptr) {} }; class RBTree { private: Node* root; void leftRotate(Node* x) { Node* y = x->right; x->right = y->left; if (y->left != nullptr) y->left->parent = x; y->parent = x->parent; if (x->parent == nullptr) root = y; else if (x == x->parent->left) x->parent->left = y; else x->parent->right = y; y->left = x; x->parent = y; } void rightRotate(Node* y) { Node* x = y->left; y->left = x->right; if (x->right != nullptr) x->right->parent = y; x->parent = y->parent; if (y->parent == nullptr) root = x; else if (y == y->parent->left) y->parent->left = x; else y->parent->right = x; x->right = y; y->parent = x; } void fixInsert(Node* k) { while (k != root && k->parent->color == RED) { if (k->parent == k->parent->parent->left) { Node* u = k->parent->parent->right; if (u != nullptr && u->color == RED) { k->parent->color = BLACK; u->color = BLACK; k->parent->parent->color = RED; k = k->parent->parent; } else { if (k == k->parent->right) { k = k->parent; leftRotate(k); } k->parent->color = BLACK; k->parent->parent->color = RED; rightRotate(k->parent->parent); } } else { Node* u = k->parent->parent->left; if (u != nullptr && u->color == RED) { k->parent->color = BLACK; u->color = BLACK; k->parent->parent->color = RED; k = k->parent->parent; } else { if (k == k->parent->left) { k = k->parent; rightRotate(k); } k->parent->color = BLACK; k->parent->parent->color = RED; leftRotate(k->parent->parent); } } } root->color = BLACK; } Node* insertNode(int data) { Node* node = new Node(data); Node* parent = nullptr; Node* temp = root; while (temp != nullptr) { parent = temp; if (data < temp->data) temp = temp->left; else temp = temp->right; } node->parent = parent; if (parent == nullptr) root = node; else if (data < parent->data) parent->left = node; else parent->right = node; fixInsert(node); return node; } Node* findMin(Node* node) { while (node->left != nullptr) node = node->left; return node; } Node* findNode(int data) { Node* temp = root; while (temp != nullptr && temp->data != data) { if (data < temp->data) temp = temp->left; else temp = temp->right; } return temp; } void transplant(Node* u, Node* v) { if (u->parent == nullptr) root = v; else if (u == u->parent->left) u->parent->left = v; else u->parent->right = v; if (v != nullptr) v->parent = u->parent; } void deleteFixup(Node* x) { while (x != root && (x == nullptr || x->color == BLACK)) { if (x == x->parent->left) { Node* w = x->parent->right; if (w != nullptr && w->color == RED) { w->color = BLACK; x->parent->color = RED; leftRotate(x->parent); w = x->parent->right; } if (w == nullptr || (w->left == nullptr || w->left->color == BLACK) && (w->right == nullptr || w->right->color == BLACK)) { if (w != nullptr) w->color = RED; x = x->parent; } else { if (w->right == nullptr || w->right->color == BLACK) { if (w->left != nullptr) w->left->color = BLACK; w->color = RED; rightRotate(w); w = x->parent->right; } w->color = x->parent->color; x->parent->color = BLACK; if (w->right != nullptr) w->right->color = BLACK; leftRotate(x->parent); x = root; } } else { Node* w = x->parent->left; if (w != nullptr && w->color == RED) { w->color = BLACK; x->parent->color = RED; rightRotate(x->parent); w = x->parent->left; } if (w == nullptr || (w->right == nullptr || w->right->color == BLACK) && (w->left == nullptr || w->left->color == BLACK)) { if (w != nullptr) w->color = RED; x = x->parent; } else { if (w->left == nullptr || w->left->color == BLACK) { if (w->right != nullptr) w->right->color = BLACK; w->color = RED; leftRotate(w); w = x->parent->left; } w->color = x->parent->color; x->parent->color = BLACK; if (w->left != nullptr) w->left->color = BLACK; rightRotate(x->parent); x = root; } } } if (x) x->color = BLACK; } void deleteNode(int data) { Node* z = findNode(data); if (z == nullptr) return; Node* y = z; Node* x; Color y_original_color = y->color; if (z->left == nullptr) { x = z->right; transplant(z, z->right); } else if (z->right == nullptr) { x = z->left; transplant(z, z->left); } else { y = findMin(z->right); y_original_color = y->color; x = y->right; if (y->parent == z) { if (x) x->parent = y; } else { transplant(y, y->right); y->right = z->right; y->right->parent = y; } transplant(z, y); y->left = z->left; y->left->parent = y; y->color = z->color; } delete z; if (y_original_color == BLACK) { deleteFixup(x); } } void preorderHelper(Node* node) { if (node == nullptr) return; cout << node->data << "(" << (node->color == BLACK ? "B" : "R") << ") "; preorderHelper(node->left); preorderHelper(node->right); } Node* getMinNode() { if (root == nullptr) return nullptr; Node* p = root; while (p->left != nullptr) p = p->left; return p; } Node* getMaxNode() { if (root == nullptr) return nullptr; Node* p = root; while (p->right != nullptr) p = p->right; return p; } public: RBTree() : root(nullptr) {} void insert(int data) { insertNode(data); } void remove(int data) { deleteNode(data); } void preorder() { preorderHelper(root); cout << endl; } void printMinMax() { Node* minNode = getMinNode(); Node* maxNode = getMaxNode(); if (minNode && maxNode) { cout << minNode->data << " " << maxNode->data << endl; } } bool isEmpty() { return root == nullptr; } }; int main() { RBTree tree; int N; cin >> N; for (int i = 0; i < N; ++i) { int val; cin >> val; tree.insert(val); } tree.preorder(); tree.printMinMax(); int M; cin >> M; for (int i = 0; i < M; ++i) { int val; cin >> val; tree.remove(val); } if (tree.isEmpty()) { cout << "Null" << endl; } else { tree.preorder(); } return 0; } ``` --- # 知识点 - **红黑树插入修复**:通过变色与旋转维持平衡,确保红节点无红子。 - **红黑树删除修复**:删除黑节点可能导致黑高失衡,需通过兄弟节点调整恢复。 - **前序遍历与最值查找**:前序遍历遵循中左右顺序;最小值位于最左,最大值位于最右。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值