首先,我们来理一遍题意,第一行输入n是整数序列长度,且整数值小于N,第二行为整数序列A1~An,f(x)是序列中小于等于x的整数里最大的数的下标。我们需要计算的是sum=f(0)+f(1)+...+f(N-1)。
本来没什么思路,但一看到样例解释,这不就是前缀和+差分嘛!
用样例1来解释一下思路:
思路:根据题意,当x<2时,序列中小于等于x的最大数是0,下标为0,即f(0),f(1)都为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。
因为f(x)某一段范围内的值都相等,且每一段范围内f(x)的值比前一段范围内的都要大1。所以我们可以让f(x)在范围[A[1],N-1]的值为1,后面每段范围的值在原基础上+1,即每段范围[A[i],N-1]的值++,由此想到可以用差分和前缀和的方法。
开始解题:我们设置一个差分数组dif,dif[i]表示的是f(i)-f(i-1),现在要使下标为[2,9]的f(x)值都要+1,那么对于下标为[2,9]的元素来说,它们的差分不会改变,因为大家都加了1,所以对一个范围内的值操作,影响的只是范围内与范围外的值的差分,即范围的临界的差分。所以dif[2]++即可。同理,我们要使下标为[5,9]的f(x)值都要+1,dif[5]++即可。所以最后,我们只做了dif[2]++,dif[5]++,dif[8]++的工作,从而求出了f(x)的差分数组。
根据定理:f(x)=dif[1]+dif[2]+...+dif[x]=f(x)-f(0),最后再求f(x)的和即可。
代码如下:
思路来源于:https://www.cnblogs.com/yongcheng137blogs/p/15412952.html
202109-2 非零段划分也是这个方法