1027 Larry and Inversions (35 分)

1027 Larry and Inversions (35 分)

又要找工作开始刷题了(等大佬内推),这道题题意很简单,给一个1到N的数字的随机顺序数组,若分别将所有的子数组逆序表示,求所有的逆序数。

暴力解法

暴力做法很简单,只需先求总数组A的逆序数,在考虑子数组中的逆序数就好了。假设原数组的逆序数RV(0,N)为NA,子数组大小为N,总组合数为N×(N-1)/2,子数组逆序数RV(i,j)为M,那么反向后逆序数为N*(N-1)/2-M,和原来的差距为N*(N-1)/2-M-M=N*(N-1)/2-2M,那么解答为NA+N(N-1)/2-2*M。求逆序数RV(i,j)的算法暴力解法(N2)遍历即可。暴力解法可以过两个点。这样每做一个子数组复杂度为O(N2),总复杂度为O(N4 )。

解法

关键点在于求解逆序数,求解逆序数时,可以看到RV(i,j),与RV(i,j-1)其实只差一个数字。那么如果我们每次求解RV(i,j)时,只把A[j]和A[i-j]作对比,记录那些A[j]3)。
但是这对于1000的数组来说还是太大,我们引进树状数组,数状数组是一种查询为O(log(N))的数据结构,我们可以借助它查询A[i-j]中大于A[j]的个数而只需要O(log(N))的时间复杂度,那么总时间复杂度为O(N2log(N)),正解。

#include 
#include 
using namespace std;
int dis[1002][1002];
class TreeArray{
public:
    TreeArray(){arr=vector<int>(1002);};
    void insert(int t){
        while(t<1002){
            arr[t]+=1;
            t+=lowbit(t);
        }
    }
    void init(){
        for(int i=0;i<1002;i++){
            arr[i]=0;
        }
    }

    int getSum(int t){
        int sum=0;
        while(t>0){
            sum+=arr[t];
            t-=lowbit(t);
        }
        return sum;
    }
    inline int lowbit(int t){
        return (t&-t);
    }
    vector<int> arr;
};
void init(){
    for(int i=0;i<1001;i++){
        for(int j=0;j<1001;j++)
            dis[i][j]=0;
    }
}
int main(){
    TreeArray tr;
    init();
    int N;
    cin>>N;
    int temp;
    vector<int> num;
    for(int i=0;i<N;i++){
        cin>>temp;
        num.push_back(temp);
    }
    long long numReverse=0;
    for(int i=0;i<num.size();i++){
        dis[i][i]=0;
        tr.init();
        tr.insert(num[i]);
        for(int j=i+1;j<num.size();j++){
            if(num[i]>num[j]){
                numReverse++;
                
            }
            else{
            }
            dis[i][j]=dis[i][j-1]+j-i-tr.getSum(num[j]);
            tr.insert(num[j]);
        }
    }
    for(int i=0;i<num.size();i++){
        cout<<numReverse;
        if(i!=num.size()-1)
        cout<<" ";
        long long change=0;
        for(int j=i+1;j<num.size();j++){
            change=((j-i+1)*(j-i))/2-2*dis[i][j];
            cout<<change+numReverse<<" ";
            
        }
    }


}

你可能感兴趣的:(PAT,T_LEVEL)