首页 > 试题广场 >

计算数组的小和

[编程题]计算数组的小和
  • 热度指数:10136 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
数组小和的定义如下:
(其中 的定义是第 i 个数的左侧小于等于 的个数)

例如,数组 s = [1, 3, 5, 2, 4, 6] ,在 s[0] 的左边小于或等于 s[0] 的数的和为 0 ; 在 s[1] 的左边小于或等于 s[1] 的数的和为 1 ;在 s[2] 的左边小于或等于 s[2] 的数的和为 1+3=4 ;在 s[3] 的左边小于或等于 s[3] 的数的和为 1 ;
在 s[4] 的左边小于或等于 s[4] 的数的和为 1+3+2=6 ;在 s[5] 的左边小于或等于 s[5] 的数的和为 1+3+5+2+4=15 。所以 s 的小和为 0+1+4+1+6+15=27
给定一个数组 s ,实现函数返回 s 的小和

数据范围:

输入描述:
第一行有一个整数N。表示数组长度
接下来一行N个整数表示数组内的数


输出描述:
一个整数表示答案
示例1

输入

6
1 3 5 2 4 6

输出

27
示例2

输入

1
1

输出

0

备注:

// 结果过大会导致整型溢出,注意要用long long类型
#include <stdio.h>
#include <stdlib.h>

long long minSum(int *arr, int l, int r);

long long merge(int *arr, int l, int m, int r);

int main(void) {
    int *arr, n;
    scanf("%d", &n);
    arr = (int *) malloc(n * sizeof(int));
    for (int i = 0; i < n; i++) {
        scanf("%d", arr + i);
    }
    printf("%ld\n", minSum(arr, 0, n - 1));
    return 0; 
}

long long minSum(int *arr, int l, int r) {
    if (l == r)
        return 0;
    int m = (l + r) / 2;
    return minSum(arr, l, m) 
        + minSum(arr, m + 1, r) 
        + merge(arr, l, m, r);
}

long long merge(int *arr, int l, int m, int r) {
    int n = r - l + 1;
    int *help = (int *) malloc(n * sizeof(int));
    int index = 0;
    
    int p1 = l, p2 = m + 1;
    long long sum = 0;
    while (p1 <= m && p2 <= r) {
        if (arr[p1] <= arr[p2]) {
            sum += (r - p2 + 1) * arr[p1];
            help[index++] = arr[p1++];
        } else {
            help[index++] = arr[p2++];
        }
    }
    while (p1 <= m) {
        help[index++] = arr[p1++];
    }
    while (p2 <= r) {
        help[index++] = arr[p2++];
    }
    for (int i = 0; i < n; i++) {
        arr[l + i] = help[i];
    }
    return sum;
}

发表于 2022-04-02 21:34:35 回复(0)

问题信息

上传者:小小
难度:
1条回答 8479浏览

热门推荐

通过挑战的用户

查看代码