202112-1 序列查询
题目链接:http://118.190.20.162/view.page?gpid=T138
题意
整数序列A=[A0,A1,A2,… ,An],序列长度是n+1,序列数值范围[0,N)。
对于序列A中存在任意的整数x,f(x)是序列A中小于等于x的整数里最大的下标。
存在两种情况:
- x在序列A的数值范围内
- x大于序列A中的所有数值
求:根据给定的序列,求sum(A),sum(A)是f(0)-f(N-1)的总和
思路
可以看出求sum(A),就是求前缀和和查分
根据样例1分析如下:
根据样例1,有如下情况:
- 当x<2时,序列中小于等于x的最大数是0,下标为0,即f(0),f(0)赋值为下标值0
- 当2≤x<5时,序列中小于等于x的最大数是2,下标为1,即f(2)~f(4)赋值为下标值1
…
由此类推,可以可知当x取[A[i],A[i+1])时,序列中小于等于x的最大数是A[i],下标为i,即f(A[i])~f(A[i+1]-1)都等于i。
解题思路
- 设置两个数组dif[]和f[]
- 数组dif[]为查分数组,表示f(i)-f(i-1)
- f[]在某段范围内的值相等,且每段范围都比前一段范围大1,所以让f(x)在[0,N)的值为1,后面每段范围的值在原基础上加1
- 边存边用的方式存储序列a
- 求查分数组dif[a]的数值
- 求f[i]=f[i-1]+dif[i]
- sum叠加f[i]的值
源代码
#include <iostream>
using namespace std;
int main()
{
const int M=1e7+5;
int n,N,dif[M],f[M];
int a;
cin>>n>>N;
for (int i = 1; i <= n; ++i) {
cin>>a;
dif[a]++;
}
int sum=0;
for (int i = 0; i < N; ++i) {
f[i]=f[i-1]+dif[i];
sum+=f[i];
}
cout<<sum;
return 0;
}