CSP 202112-1 序列查詢(前綴和+差分)


首先,我們來理一遍題意,第一行輸入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)的和即可。

代碼如下:

#include<bits/stdc++.h>
using namespace std;
const int M=1e7+5;
int n,N,dif[M],f[M];
int main(){
    int a;
    cin>>n>>N;
    for(int i=1;i<=n;i++){
        cin>>a;
        dif[a]++;
    }
    int res=0;
    for(int i=1;i<N;i++)
       { f[i]=f[i-1]+dif[i]; res+=f[i];}
    cout<<res;
    return 0;
}

思路來源於:https://www.cnblogs.com/yongcheng137blogs/p/15412952.html

202109-2 非零段划分也是這個方法


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM