1. 程式人生 > 實用技巧 >牛客程式設計巔峰賽S1第5場 - 青銅&白銀 C.排隊 (優先佇列,歸併排序)

牛客程式設計巔峰賽S1第5場 - 青銅&白銀 C.排隊 (優先佇列,歸併排序)

  • 題意:有\(m\)個視窗,\(n\)個人排隊,每個人都有各自的辦理時間,只有辦理完成窗口才能空出來,後面的人開始辦理,求有多少人比後面的人開始辦理的早但完成的晚.

  • 題解:我們可以用優先佇列來模擬辦理,用一個數組q來記錄辦理完成的時間,之後只要求q中逆序對的個數即可,既然求逆序對,那我們肯定用歸併排序啦~

  • 程式碼:

    class Solution {
    public:
        /**
         * 求解合法的(i,j)對的數量
         * @param n int整型 n個人
         * @param m int整型 m個視窗
         * @param a int整型vector 長度為n的vector,順序表示1-n號客人的辦理業務所需時間
         * @return long長整型
         */
        
        long long q[1000010];
        long long t[1000010];
        long long res;
        priority_queue<long long,vector<long long>,greater<long long>> h;
        
        long long merge_sort(long long q[],int l,int r){
        if(l==r) return 0;
        int mid=(l+r)>>1;
        res=merge_sort(q,l,mid)+merge_sort(q,mid+1,r);
        int i=l,j=mid+1;
        int cnt=0;
        while(i<=mid && j<=r){
            if(q[i]<=q[j]) t[++cnt]=q[i++];
            else{
                t[++cnt]=q[j++];
                res+=mid-i+1;
            }
        }
        while(i<=mid) t[++cnt]=q[i++];
        while(j<=r) t[++cnt]=q[j++];
    
        for(int i=l,j=1;i<=r;++i,++j) q[i]=t[j];
    
        return res;
        }
        long long getNumValidPairs(int n, int m, vector<int>& a) {
           
            
            for(int i=0;i<m;++i){
                h.push(0);
            }
            
            for(int i=0;i<n;++i){
                long long tmp=h.top()+a[i];
                q[i+1]=tmp;
                h.pop();
                h.push(tmp);
            }
            
            res=merge_sort(q,1,n);
            
            return res;
        }
    };