问题描述
给定一个数组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]。
对于我这个编程小小白来说还是绕了好一会儿,记录一下成果,继续加油!