- 打卡等级:偶尔看看
- 打卡总天数:14
- 打卡月天数:14
- 打卡总奖励:206
- 最近打卡:2025-07-31 09:16:38
管理员
- 积分
- 20261
|
 一、问题分析这道题目要求我们计算将一个数组中的元素依次插入到一个初始为空的数组中时,所有插入操作的总代价。每次插入的代价定义为: 当前数组中严格小于插入元素的数目 当前数组中严格大于插入元素的数目
两者中的较小值
二、解题思路我们可以使用树状数组(Fenwick Tree)来高效解决这个问题: 使用树状数组维护当前数组中各数字的出现次数 对于每个插入元素,快速查询小于和大于它的元素数量 计算每次插入的代价并累加
三、C++代码实现C++
class FenwickTree {private: vector<int> tree;public: FenwickTree(int size) : tree(size + 1) {} void update(int index, int delta) { while (index < tree.size()) { tree[index += delta; index += index & -index; } } int query(int index) { int sum = 0; while (index > 0) { sum += tree[index; index -= index & -index; } return sum; }};class Solution {public: int createSortedArray(vector<int>& instructions) { const int MOD = 1e9 + 7; // 离散化处理 vector<int> sorted = instructions; sort(sorted.begin(), sorted.end()); sorted.erase(unique(sorted.begin(), sorted.end()), sorted.end()); FenwickTree ft(sorted.size()); int totalCost = 0; for (int num : instructions) { // 获取离散化后的索引 int rank = lower_bound(sorted.begin(), sorted.end(), num) - sorted.begin() + 1; // 查询小于当前数的数量 int less = ft.query(rank - 1); // 查询小于等于当前数的数量 int lessEqual = ft.query(rank); // 当前数的出现次数 int same = lessEqual - less; // 大于当前数的数量 = 总数 - 小于等于的数量 int greater = ft.query(sorted.size()) - lessEqual; // 计算当前插入代价 int cost = min(less, greater); totalCost = (totalCost + cost) % MOD; // 更新树状数组 ft.update(rank, 1); } return totalCost; }};
四、代码详解FenwickTree类:
离散化处理:
主逻辑:
遍历instructions数组 对每个元素查询小于和大于它的数量 计算当前插入代价并累加 更新树状数组
复杂度分析:
五、算法优化六、扩展思考掌握这种树状数组解法,能够帮助你解决许多类似的动态规划和查询问题!
|
|