Weekly Contest 387

浅花迷人發表於2024-03-09

Problem A

Distribute Elements Into Two Arrays I

思路

按照題意模擬即可.

程式碼

class Solution {
    public int[] resultArray(int[] nums) {
        int n = nums.length;
        int[] ans = new int[n];
        int[] arr1 = new int[n];
        int[] arr2 = new int[n];
        int l = 1;
        int r = 1;
        arr1[0] = nums[0];
        arr2[0] = nums[1];
        for(int i = 2;i<n;++i){
            if(arr1[l-1]>arr2[r-1]){
                arr1[l++] = nums[i];
            }
            else{
                arr2[r++] = nums[i];
            }
        }
        int i = 0;
        for(int j = 0;j<l;++j){
            ans[i++] = arr1[j];
        }
        for(int j = 0;j<r;++j){
            ans[i++] = arr2[j];
        }
        return ans;
    }
}

Problem B

Count Submatrices with Top-Left Element and Sum Less Than k

思路

二維陣列字首和

程式碼

class Solution {
    public int countSubmatrices(int[][] grid, int k) {
        int n = grid.length;
        int m = grid[0].length;
        int[][] dp = new int[n+1][m+1];
        // dp[0][0] = grid[0][0];
        int cnt = 0;
        for(int i = 1;i<=n;++i){
            for(int j = 1;j<=m;++j){
                dp[i][j] = dp[i-1][j]+dp[i][j-1]-dp[i-1][j-1]+grid[i-1][j-1];
                if(dp[i][j]<=k){
                    ++cnt;
                }
            }
        }
        return cnt;
        
    }
}

Problem C

Minimum Operations to Write the Letter Y on a Grid

思路

題目不難 按照座標列舉 求出Y型區域每個數字出現的次數以及非Y型區域每個數字的出現次數,然後列舉兩部分的最終字元即可

程式碼

class Solution {
    public int minimumOperationsToWriteY(int[][] grid) {
        int n = grid.length;
        int[] cnt = new int[3];
        for(int i = 0;i<n;++i){
            for(int j = 0;j<n;++j){
                cnt[grid[i][j]]++;
            }
        }
        int[] Y_cnt = new int[3];
        int d = (n+1)/2;
        for(int i = 0;i<d;++i){
            Y_cnt[grid[i][i]]++;
            Y_cnt[grid[i][n-i-1]]++;
            Y_cnt[grid[i+d-1][d-1]]++;
        }
        Y_cnt[grid[d-1][d-1]]-=2;
        cnt[0]-=Y_cnt[0];
        cnt[1]-=Y_cnt[1];
        cnt[2]-=Y_cnt[2];
        int s1 = cnt[0]+cnt[1]+cnt[2];
        int s2 = Y_cnt[0]+Y_cnt[1]+Y_cnt[2];
        int ans  = n*n*n;
        for(int i = 0;i<3;++i){
            for(int j = 0;j<3;++j){
                if(i==j){
                    continue;
                }
                int cal = s1-cnt[i]+s2-Y_cnt[j];
                ans = Math.min(ans,cal);
            }
        }
        return ans;
        
    }
}
        

Problem D

Distribute Elements Into Two Arrays II

思路

主要問題在於如何兩個有序的序列,其他的按照題意模擬即可
比賽時使用的python現有的資料結構進行的模擬 對於 greaterCount則使用二分查詢實現
實際上應該使用兩個樹狀陣列進行實現,要注意題目中數的取值範圍是1e9 所以應該先離散化再取值

程式碼

比賽程式碼

def greaterCount(heap, val):
    l = 0
    r = len(heap)
    while(l<r):
        mid= (l+r)>>1
        if(heap[mid]<val):
            l = mid+1
        else:
            r = mid
    return l+1

def distribute(nums):

    arr1 = [nums[0]]
    arr2 = [nums[1]]
    h1 = [-nums[0]]
    h2 = [-nums[1]]
    for i in range(2, len(nums)):
        count1 = greaterCount(h1, -nums[i])
        count2 = greaterCount(h2, -nums[i])
        if count1 > count2:
            bisect.insort_left(h1, -nums[i])
            arr1.append(nums[i])
        elif count1 < count2:
            bisect.insort_left(h2, -nums[i])
            arr2.append(nums[i])
        else:
            if len(arr1) <= len(arr2):
                bisect.insort_left(h1, -nums[i])
                arr1.append(nums[i])
            else:
                bisect.insort_left(h2, -nums[i])
                arr2.append(nums[i])
    result = arr1 + arr2
    return result
class Solution:

    def resultArray(self, nums: List[int]) -> List[int]:
        return distribute(nums)

補題程式碼

class Solution {
    public int greaterCount(BIT b,int val,int cnt){
        return cnt - b.getSum(val);
    }
    public int[] resultArray(int[] nums) {
        TreeSet<Integer> tree = new TreeSet<Integer>();
        for(int num:nums){
            tree.add(num);
        }
        Map<Integer,Integer> map = new HashMap<>();
        int i = 1;
        for(int k:tree){
            map.put(k,i++);
            
        }
        List<Integer> l1 = new ArrayList<>();
        List<Integer> l2 = new ArrayList<>();
        l1.add(nums[0]);
        l2.add(nums[1]);
        int cnt1 = 1;
        int cnt2 = 1;
        BIT t1 = new BIT(i);
        BIT t2 = new BIT(i);
        t1.add(map.get(nums[0]),1);
        t2.add(map.get(nums[1]),1);
        for( i = 2;i<nums.length;++i){
            int g1 = greaterCount(t1,map.get(nums[i]),cnt1);
            int g2 = greaterCount(t2,map.get(nums[i]),cnt2);
            // System.out.println(" "+g1+ " " + g2);
            if(g1>g2||(g1==g2&&cnt1<=cnt2)){
                ++cnt1;
                l1.add(nums[i]);
                t1.add(map.get(nums[i]),1);
            }
            else{
                ++cnt2;
                l2.add(nums[i]);
                t2.add(map.get(nums[i]),1);
            }
        }
        int[] ans = new int[nums.length];
       
        l1.addAll(l2);
        for(int j = 0;j<nums.length;++j){
            ans[j] = l1.get(j);
        }
        return ans;
    }
}
class BIT {
    
    int n;
    int[] tr;
    BIT(int n){
        this.n = n;
        tr = new int[n+1];
    }
    public static int lowbit(int x){
        return x&-x;
    }
    public  void add(int x,int v){
        while(x<=n){
            tr[x]+=v;
            x+=lowbit(x);
        }
    }
    public int getSum(int k){
        int ret = 0;
        while(k>0){
            ret+=tr[k];
            k-=lowbit(k);
        }
        return ret;
    }

}

總結

本場簡單 成功AK 但是第四題的思路不清晰 補學了下樹狀陣列

相關文章