3.28学习心得
发布日期:2021-05-14 09:16:06 浏览次数:22 分类:精选文章

本文共 2148 字,大约阅读时间需要 7 分钟。

为了解决这两个问题,我们需要分别处理不同的算法挑战。以下是详细的解决方案:

问题一:最少交换次数

问题描述:给定一个数列,通过交换相邻的两个元素,使数列变成升序,并求最少需要交换的次数。

解决思路

要使数列有序,最少交换次数等于数列中的逆序对数。逆序对是指数组中较大的数在较小的数前面。计算逆序对的方法有两种常用方法:归并排序和树状数组。由于数列长度较大(最多1e5),树状数组方法更高效。

树状数组的实现

树状数组用于高效计算前缀和,用于统计小于当前元素的数目。通过从右到左遍历数组,每次查询前缀和,累加到逆序对计数中。

代码实现

#include 
using namespace std;
void update(int idx, vector
& c, int n) {
while(idx <= n) {
c[idx]++;
idx += idx & -idx;
}
}
int query(int idx, const vector
& c) {
int sum = 0;
while(idx > 0) {
sum += c[idx];
idx -= idx & -idx;
}
return sum;
}
int main() {
int n, m;
cin >> n >> m;
vector
a(n);
for(int i=0; i
> num;
a[i] = num;
}
vector
c(n+2, 0); long long ans = 0; for(int i = n-1; i >=0; --i) { int num = a[i]; int cnt = query(num -1); ans += cnt; update(num, c, n); } cout << ans << endl; return 0; }

问题二:分割数组为m个部分

问题描述:将n天的开销分成m个连续的月份,使最大月份开销最小。

解决思路

使用二分法确定最小的最大月份开销。二分法的关键在于检查给定mid是否可行,即能否分割成m个月份,每个月份的总和不超过mid。

二分法的实现

  • 初始化left为数组最大值,right为总和除以m。
  • 在每次二分中,计算mid,检查是否可行。
  • 如果可行,更新ans,尝试更小的mid;否则,尝试更大的mid。
  • 代码实现

    #include 
    #include
    #include
    using namespace std;
    bool check(int x, const vector
    & a, int m) {
    int current_sum = 0;
    int month_count = 0;
    for (int num : a) {
    current_sum += num;
    if (current_sum > x) {
    month_count++;
    current_sum = 0;
    }
    if (month_count > m) {
    return false;
    }
    }
    return month_count <= m;
    }
    int main() {
    int n, m;
    cin >> n >> m;
    vector
    a(n);
    for(int i=0; i
    > num; a[i] = num; } int left = *max_element(a.begin(), a.end()); int right = accumulate(a.begin(), a.end(), 0) / m; int ans = right; while (left <= right) { int mid = (left + right) / 2; if (check(mid, a, m)) { ans = mid; right = mid - 1; } else { left = mid + 1; } } cout << ans << endl; return 0; }

    总结

  • 问题一使用树状数组高效计算逆序对数,确保O(n log n)时间复杂度。
  • 问题二采用二分法快速确定最小可行值,确保在O(log(max_sum))时间内找到最优解。
  • 上一篇:4.4学习心得
    下一篇:3.21学习心得

    发表评论

    最新留言

    感谢大佬
    [***.8.128.20]2025年04月11日 02时30分23秒