【蓝桥 重新排序】(差分数组)

问题描述

给定一个数组A和一些查询Li,Ri,求数组中第Li至第Ri个元素之和。
小蓝觉得这个问题很无聊🆒,于是他想重新排列下数组,使得最终每个查询结果的和尽可能地大。小蓝想知道相比原数组,所有查询结果的总和最多可以增加多少?

输入格式

输入第一行包含一个整数n;
第二行包含n个整数A1, A2, …,An,相邻两个整数之间用一个空格分隔;
第三行包含一个整数m表示查询的数目;
接下来m行,每行包含两个整数Li、Ri, 相邻两个整数之间用一个空格分隔。

输出格式

输出一行包含一个整数表示答案。

样例输入

5
1 2 3 4 5
2
1 3
2 5

样例输出

4

#include <iostream>
#include<algorithm>
using namespace std;
int main()
{
    long long num[100001];
    int rate[100001],sum[100001];
    //rates数组为差分数组,sum数组可看成原数组
    long long int ratesum=0;
    long long int sum1=0,sum2=0;
    int m,n;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>num[i];
    }
    cin>>m;
    int l,r;
    for(int j=0;j<m;j++)
    {
    cin>>l>>r;
    rate[l-1]++;//每次循环范围内频率加一
    rate[r]--;
    }
    for(int i=0;i<n;i++)
    {
        sumrate+=rate[i];
        sum[i]=sumrate;//差分数组的应用
    }
    for(int i=0;i<n;i++)
    {
        sum1+=num[i]*sum[i];
    }
    sort(&sum[0],&sum[n]);//数和频率排序
    sort(&num[0],&num[n]);
    for(int i=0;i<n;i++)
    {
        sum2+=num[i]*sum[i];//大的数对应大的频率
    }
   cout<<sum2-sum1;
   return 0;
}

原始数值数组 num 包含了 5 个元素:1, 2, 3, 4, 5。接着有两个区间操作:

  • 第一个区间操作是 (1, 3),表示将第 1 到第 3 个数值加 1。
  • 第二个区间操作是 (2, 5),表示将第 2 到第 5 个数值加 1。

根据这些区间操作可以计算差分数组 rate,以记录区间操作的变化情况。初始时,差分数组的所有元素均为 0。

对于第一个区间操作 (1, 3),在差分数组中的处理如下:

  • rate[0] 加 1,表示从 num[0]num[1] 的区间发生了变化,即 rate[0] = 1
  • rate[2] 减 1,表示从 num[2]num[3] 的区间发生了变化,即 rate[2] = -1

对于第二个区间操作 (2, 5),在差分数组中的处理如下:

  • rate[1] 加 1,表示从 num[1]num[2] 的区间发生了变化,即 rate[1] = 1
  • rate[4] 减 1,表示从 num[4]num[5] 的区间发生了变化,即 rate[4] = -1

根据上述操作,最终的差分数组 rate 将会是:[1, 1, -1, 0, -1]。
计算出频率和数组 sum 如下:
第一个元素:初始值为 0,加上 rate[0],即 0 + 1 = 1;
第二个元素:上一个元素的值 1 加上 rate[1],即 1 + 1 = 2;
第三个元素:上一个元素的值 2 加上 rate[2],即 2 + (-1) = 1;
第四个元素:上一个元素的值 1 加上 rate[3],即 1 + 0 = 1;
第五个元素:上一个元素的值 1 加上 rate[4],即 1 + (-1) = 0。 sum 为 [1, 2, 1, 1, 0]。

对于我这个编程小小白来说还是绕了好一会儿,记录一下成果,继续加油!

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值