/*
Problem: Maximize total value from using tools
You have n tools. Tool i can be used a[i] times.
Each time you use a tool, its value decreases:
- First use gives a[i] points
- Second use gives a[i]-1 points
- Third use gives a[i]-2 points
- ... and so on down to 1 point
You can make exactly m total uses across all tools.
Find the maximum total points you can get.
Example:
Tools: [5, 3] (tool 1 can be used 5 times, tool 2 can be used 3 times)
If m = 4 uses allowed:
Best strategy: Take the highest value uses
- Use tool 1 once: get 5 points
- Use tool 2 once: get 3 points
- Use tool 1 again: get 4 points
- Use tool 2 again: get 2 points
Total = 5 + 3 + 4 + 2 = 14 points
==================================================================================
HOW WE SOLVE THIS:
==================================================================================
The greedy approach: Always pick the highest value use available.
But checking all possible uses one by one would be too slow for large inputs.
BETTER IDEA: Use binary search!
Key insight: If we decide on a "cutoff value" T, we can quickly calculate:
"How many uses give value >= T?"
For a tool with max value x:
- If T <= x, it has uses worth x, x-1, x-2, ..., T
- That's (x - T + 1) uses with value >= T
Once we know the cutoff T:
1. Take ALL uses with value > T (these are the best)
2. Fill up remaining uses with value exactly T
How to find the right cutoff T?
- Binary search!
- We want the HIGHEST value T where there are at least m uses with value >= T
- This ensures we take the best m uses possible
Example walkthrough:
Tools: [5, 3], m = 4
Try T = 4:
- Tool 1 (value 5): has uses worth 5, 4 → that's 2 uses
- Tool 2 (value 3): value 3 < 4 → no uses
- Total: 2 uses with value >= 4
- Is 2 >= 4? No, so T = 4 is too high
Try T = 2:
- Tool 1 (value 5): has uses worth 5, 4, 3, 2 → that's 4 uses
- Tool 2 (value 3): has uses worth 3, 2 → that's 2 uses
- Total: 6 uses with value >= 2
- Is 6 >= 4? Yes! So T = 2 works
Try T = 3:
- Tool 1 (value 5): has uses worth 5, 4, 3 → that's 3 uses
- Tool 2 (value 3): has uses worth 3 → that's 1 use
- Total: 4 uses with value >= 3
- Is 4 >= 4? Yes! T = 3 is even better!
So the answer with cutoff T = 3:
- Take all values > 3: from tool 1 get (5 + 4) = 9 points (2 uses)
- Need 2 more uses with value = 3: get 3 + 3 = 6 points
- Total: 9 + 6 = 15 points
Special case: If m > total available uses, just use everything!
Time complexity: O(n log(max_value)) - binary search × counting
Space complexity: O(n) for storing the tools
==================================================================================
*/
#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n; // number of tools
long long m; // number of uses we're allowed to make
cin >> n >> m;
vector<long long> tool(n); // tool[i] = max value of tool i
long long max_tool_value = 0;
__int128 total_uses_available = 0;
for(int i = 0; i < n; i++){
cin >> tool[i];
if(tool[i] > max_tool_value) {
max_tool_value = tool[i];
}
total_uses_available += tool[i];
}
// Special case: if we can use more than what's available, just take everything
if((__int128)m > total_uses_available){
__int128 answer = 0;
for(long long value : tool){
// Sum of 1 + 2 + ... + value = value * (value + 1) / 2
answer += (__int128)value * (value + 1) / 2;
}
// Print the 128-bit result
if(answer == 0){
cout << 0 << "\n";
} else {
string output;
__int128 temp = answer;
while(temp > 0){
output.push_back('0' + (temp % 10));
temp /= 10;
}
reverse(output.begin(), output.end());
cout << output << "\n";
}
return 0;
}
// Function: count how many uses have value >= threshold
auto count_high_value_uses = [&](long long threshold) -> __int128 {
__int128 total = 0;
for(long long value : tool){
// Tool with max value has uses: value, value-1, value-2, ..., 1
// How many are >= threshold?
// That's value, value-1, ..., threshold which is (value - threshold + 1) uses
if(value >= threshold) {
total += (value - threshold + 1);
}
}
return total;
};
// Binary search to find the highest threshold where we have at least m uses
long long low = 1, high = max_tool_value;
long long threshold = 1;
while(low <= high){
long long middle = low + (high - low) / 2;
// Can we get at least m uses with value >= middle?
if(count_high_value_uses(middle) >= (__int128)m){
threshold = middle; // Yes! Try a higher threshold
low = middle + 1;
} else {
high = middle - 1; // No, threshold is too high
}
}
// Now calculate the total value using this threshold
__int128 answer = 0;
__int128 uses_so_far = 0;
// Step 1: Take all uses with value STRICTLY GREATER than the threshold
for(long long value : tool){
if(value > threshold){
// Take values: value, value-1, ..., (threshold + 1)
long long count = value - threshold;
uses_so_far += count;
// Sum of arithmetic sequence: (first + last) * count / 2
// first = value, last = threshold + 1
answer += (__int128)(value + (threshold + 1)) * count / 2;
}
}
// Step 2: Fill remaining uses with value exactly equal to the threshold
long long uses_left = (long long)((__int128)m - uses_so_far);
answer += (__int128)uses_left * threshold;
// Print the 128-bit result
if(answer == 0){
cout << 0 << "\n";
return 0;
}
string output;
__int128 temp = answer;
while(temp > 0){
output.push_back('0' + (temp % 10));
temp /= 10;
}
reverse(output.begin(), output.end());
cout << output << "\n";
return 0;
}