|
| 1 | +// Problem Number: 2818 |
| 2 | + |
| 3 | +// Apply Operations to Maximize Score. |
| 4 | + |
| 5 | +class Solution { |
| 6 | + public int maximumScore(List<Integer> nums, int k) { |
| 7 | + final int n = nums.size(); |
| 8 | + final int mx = Collections.max(nums); |
| 9 | + final int[] minPrimeFactors = sieveEratosthenes(mx + 1); |
| 10 | + final int[] primeScores = getPrimeScores(nums, minPrimeFactors); |
| 11 | + int ans = 1; |
| 12 | + |
| 13 | + int[] left = new int[n]; |
| 14 | + Arrays.fill(left, -1); |
| 15 | + int[] right = new int[n]; |
| 16 | + Arrays.fill(right, n); |
| 17 | + Deque<Integer> stack = new ArrayDeque<>(); |
| 18 | + |
| 19 | + for (int i = n - 1; i >= 0; --i) { |
| 20 | + while (!stack.isEmpty() && primeScores[stack.peek()] <= primeScores[i]) |
| 21 | + left[stack.pop()] = i; |
| 22 | + stack.push(i); |
| 23 | + } |
| 24 | + |
| 25 | + stack.clear(); |
| 26 | + for (int i = 0; i < n; ++i) { |
| 27 | + while (!stack.isEmpty() && primeScores[stack.peek()] < primeScores[i]) |
| 28 | + right[stack.pop()] = i; |
| 29 | + stack.push(i); |
| 30 | + } |
| 31 | + |
| 32 | + Pair<Integer, Integer>[] numAndIndexes = new Pair[n]; |
| 33 | + |
| 34 | + for (int i = 0; i < n; ++i) |
| 35 | + numAndIndexes[i] = new Pair<>(nums.get(i), i); |
| 36 | + |
| 37 | + Arrays.sort(numAndIndexes, |
| 38 | + Comparator.comparing(Pair<Integer, Integer>::getKey, Comparator.reverseOrder()) |
| 39 | + .thenComparingInt(Pair<Integer, Integer>::getValue)); |
| 40 | + |
| 41 | + for (Pair<Integer, Integer> numAndIndex : numAndIndexes) { |
| 42 | + final int num = numAndIndex.getKey(); |
| 43 | + final int i = numAndIndex.getValue(); |
| 44 | + |
| 45 | + final long rangeCount = (long) (i - left[i]) * (right[i] - i); |
| 46 | + final long actualCount = Math.min(rangeCount, (long) k); |
| 47 | + k -= actualCount; |
| 48 | + ans = (int) ((1L * ans * modPow(num, actualCount)) % MOD); |
| 49 | + } |
| 50 | + |
| 51 | + return ans; |
| 52 | + } |
| 53 | + |
| 54 | + private static final int MOD = 1_000_000_007; |
| 55 | + |
| 56 | + private long modPow(long x, long n) { |
| 57 | + if (n == 0) |
| 58 | + return 1; |
| 59 | + if (n % 2 == 1) |
| 60 | + return x * modPow(x, n - 1) % MOD; |
| 61 | + return modPow(x * x % MOD, n / 2); |
| 62 | + } |
| 63 | + |
| 64 | + private int[] sieveEratosthenes(int n) { |
| 65 | + int[] minPrimeFactors = new int[n + 1]; |
| 66 | + for (int i = 2; i <= n; ++i) |
| 67 | + minPrimeFactors[i] = i; |
| 68 | + for (int i = 2; i * i < n; ++i) |
| 69 | + if (minPrimeFactors[i] == i) // `i` is prime. |
| 70 | + for (int j = i * i; j < n; j += i) |
| 71 | + minPrimeFactors[j] = Math.min(minPrimeFactors[j], i); |
| 72 | + return minPrimeFactors; |
| 73 | + } |
| 74 | + |
| 75 | + private int[] getPrimeScores(List<Integer> nums, int[] minPrimeFactors) { |
| 76 | + int[] primeScores = new int[nums.size()]; |
| 77 | + for (int i = 0; i < nums.size(); ++i) |
| 78 | + primeScores[i] = getPrimeScore(nums.get(i), minPrimeFactors); |
| 79 | + return primeScores; |
| 80 | + } |
| 81 | + |
| 82 | + private int getPrimeScore(int num, int[] minPrimeFactors) { |
| 83 | + Set<Integer> primeFactors = new HashSet<>(); |
| 84 | + while (num > 1) { |
| 85 | + final int divisor = minPrimeFactors[num]; |
| 86 | + primeFactors.add(divisor); |
| 87 | + while (num % divisor == 0) |
| 88 | + num /= divisor; |
| 89 | + } |
| 90 | + return primeFactors.size(); |
| 91 | + } |
| 92 | +} |
0 commit comments