【堆】C003_AW_接水問題(暴力 / 堆)
阿新 • • 發佈:2020-09-12
學校裡有一個水房,水房裡一共裝有 m 個龍頭可供同學們開啟水,每個龍頭每秒鐘的供水量相等,均為 1。
現在有 n 名同學準備接水,他們的初始接水順序已經確定。
將這些同學按接水順序從 1 到 n 編號,i 號同學的接水量為 wi。
接水開始時,1 到 m 號同學各佔一個水龍頭,並同時開啟水龍頭接水。
當其中某名同學 j 完成其接水量要求 wj 後,下一名排隊等候接水的同學 k 馬上接替 j 同學的位置開始接水。
這個換人的過程是瞬間完成的,且沒有任何水的浪費。
即 j 同學第 x 秒結束時完成接水, 則 k 同學第 x+1 秒立刻開始接水。
若當前接水人數 n’ 不足 m,則只有 n’ 個龍頭供水,其它 m−n’ 個龍頭關閉。
現在給出 n 名同學的接水量,按照上述接水規則,問所有同學都接完水需要多少秒。
輸入格式
第 1 行 2 個整數 n 和 m,用一個空格隔開,分別表示接水人數和龍頭個數。
第 2 行 n 個整數 w1、w2、…、wn,每兩個整數之間用一個空格隔開,wi表示 i 號同學的接水量。
輸出格式
輸出只有一行,1 個整數,表示接水所需的總時間。
資料範圍
對於 30%的資料,n≤10,000,m≤1,000;
對於全部的資料,1≤m≤n≤1,000,000,1≤m≤100,000
輸入樣例:
5 3
4 4 1 2 1
輸出樣例:
4
方法一:暴力
在 O(n) 迴圈中巢狀一個 O(m) 迴圈取找 m 個水龍頭中最早處於閒置狀態的水龍頭,則下一個同學一定會選用該水龍頭裝水
複雜度分析
- Time:\(O(nm)\),
- Space:\(O(1)\),
方法二:堆
用堆來優化掉 O(m) 時間,先讓前m個同學取接水(放入小根堆中),下一個人的接水時間就是 A[i]+q.top()(i∈[m+1, n)),記錄過程中的最大接水時間就是答案
import java.util.*; import java.math.*; import java.io.*; public class Main{ static class Solution { void init() throws IOException { Scanner sc = new Scanner(new BufferedInputStream(System.in)); String[] t = sc.nextLine().split(" "); int n=Integer.parseInt(t[0]), m=Integer.parseInt(t[1]), A[]=new int[n]; for (int i=0; i<n; i++) { A[i]=sc.nextInt(); } int ans=0; Queue<Integer> q = new PriorityQueue<>(); for (int i=0; i<m; i++) { if (A[i]>ans) ans=A[i]; q.add(A[i]); } for (int i=m; i<n; i++) { int nx=q.poll()+A[i]; if (nx>ans) ans=nx; q.add(nx); } System.out.println(ans); } } public static void main(String[] args) throws IOException { Solution s = new Solution(); s.init(); } }
複雜度分析
- Time:\(O(nlogm)\),
- Space:\(O(m)\),