From 8247bac679c34c5c25cbb26e1ae285f3f706a603 Mon Sep 17 00:00:00 2001 From: LiiNi-coder <97495437+LiiNi-coder@users.noreply.github.com> Date: Thu, 21 Aug 2025 23:59:12 +0900 Subject: [PATCH] =?UTF-8?q?[20250821]=20PGM=20/=20LV3=20/=20=EA=B4=91?= =?UTF-8?q?=EA=B3=A0=20=EC=82=BD=EC=9E=85=20/=20=EC=9D=B4=EC=9D=B8?= =?UTF-8?q?=ED=9D=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...1\352\263\240 \354\202\275\354\236\205.md" | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 "LiiNi-coder/202508/21 PGM \352\264\221\352\263\240 \354\202\275\354\236\205.md" diff --git "a/LiiNi-coder/202508/21 PGM \352\264\221\352\263\240 \354\202\275\354\236\205.md" "b/LiiNi-coder/202508/21 PGM \352\264\221\352\263\240 \354\202\275\354\236\205.md" new file mode 100644 index 00000000..9d68cae5 --- /dev/null +++ "b/LiiNi-coder/202508/21 PGM \352\264\221\352\263\240 \354\202\275\354\236\205.md" @@ -0,0 +1,115 @@ +```java +import java.util.*; + +class Solution { + static class TimeInfo{ + int startCount; //time에 시작하는 log개수 + int endCount;//time에 끝나는 log개수 + long prefix; //time까지의 가중치 누적합 + + TimeInfo(int sc, int ec, long p){ + this.startCount = sc; + this.endCount = ec; + this.prefix = p; + } + @Override + public String toString(){ + return String.format("sc: %d, ec: %d prefix:%d", this.startCount, this.endCount, this.prefix); + } + } + + private static TreeMap timeInfos; + public String solution(String play_time, String adv_time, String[] logs) { + timeInfos = new TreeMap(); + timeInfos.put(0, new TimeInfo(0, 0, 0)); + + for(String log : logs){ + String[] temp = log.split("-"); + int startTime = convertToSeconds(temp[0]); + int endTime = convertToSeconds(temp[1]); + + timeInfos.computeIfAbsent(startTime, k -> new TimeInfo(0, 0, 0)).startCount++; + timeInfos.computeIfAbsent(endTime, k -> new TimeInfo(0, 0, 0)).endCount++; + } + + //prefix 누적합 계산 + long currentLogs = 0; + long cumulativeSum = 0; + Integer prevTime = null; + for(Map.Entry entry : timeInfos.entrySet()){ + int time = entry.getKey(); + TimeInfo info = entry.getValue(); + + if(prevTime != null){ + cumulativeSum += currentLogs * (time - prevTime); + } + info.prefix = cumulativeSum; + currentLogs += info.startCount - info.endCount; + prevTime = time; + } + + int advSeconds = convertToSeconds(adv_time); + int playSeconds = convertToSeconds(play_time); + long maxViewTime = 0; + int bestStartTime = 0; + for(int startTime = 0; startTime <= playSeconds - advSeconds; startTime++){ + int endTime = startTime + advSeconds; + long viewTime = getViewTime(startTime, endTime); + + if(viewTime > maxViewTime){ + maxViewTime = viewTime; + bestStartTime = startTime; + } + } + + return convertToHHMMSS(bestStartTime); + } + + //startTime부터 endTime까지의 총 재생시간 계산 + private long getViewTime(int startTime, int endTime){ + long endPrefix = getPrefixSum(endTime); + long startPrefix = getPrefixSum(startTime); + return endPrefix - startPrefix; + } + + //time 시점까지의 누적 재생시간 + private long getPrefixSum(int time){ + Map.Entry floorEntry = timeInfos.floorEntry(time); + if(floorEntry == null) return 0; + + int floorTime = floorEntry.getKey(); + TimeInfo floorInfo = floorEntry.getValue(); + long prefix = floorInfo.prefix; + + //구간 내 재생시간 추가 계산 + if(time > floorTime){ + long currentLogs = 0; + // floorTime 이후의 로그 수 계산 + for(Map.Entry entry : timeInfos.headMap(floorTime, true).entrySet()){ + TimeInfo info = entry.getValue(); + currentLogs += info.startCount - info.endCount; + } + prefix += currentLogs * (time - floorTime); + } + return prefix; + } + + private int convertToSeconds(String hms){ + String[] tokens = hms.split(":"); + int result = 0; + for(int i = 2, gop = 1; i>=0; i--, gop*=60){ + result += Integer.parseInt(tokens[i])*gop; + } + return result; + } + + private String convertToHHMMSS(int seconds){ + int h = seconds / 3600; + seconds %= 3600; + int m = seconds / 60; + int s = seconds % 60; + return String.format("%02d:%02d:%02d", h, m, s); + } +} + +```