DISKMOV - Editorial

PROBLEM LINK:

Practice
Contest: Division 1
Contest: Division 2
Contest: Division 3
Contest: Division 4

Author: Akshat Anil Jain
Tester: Tejas Pandey
Editorialist: Nishank Suresh

DIFFICULTY:

1912

PREREQUISITES:

None

PROBLEM:

Given an array A containing N distinct integers ranging from 1 to 2N, perform the following operation exactly K times:

  • Choose some 1 \leq x \leq 2N such that x \notin A, append x to A, and add \max(A) - x to your score

What is the maximum possible final score?

EXPLANATION:

Let’s look at how the score changes when we add a new element x to A. There are two cases:

  • If x \lt \max(A), then we get \max(A) - x added to the score
  • Otherwise, we must have x = \max(A), in which case we add 0 to the score.

Ideally, we’d like as many operations of the first type as possible, since they’re profitable. Note that the score of the first operation is maximized when x is as small as possible and \max(A) is as large as possible.

This gives us a strategy. Let M denote the initial maximum of A, before any operations are done.

  • Suppose we add K elements that do not change the maximum, i.e, they are all \lt M. Then, of course we choose the smallest K elements to insert.
  • Suppose we add some element that does change the maximum.
    • It’s optimal to add this element first so that all later operations have a higher score.
    • It’s optimal to add as large a maximum as possible, so let’s just choose 2N to add in the first move
    • The other K-1 elements then should be chosen to be as small as possible to maximize the score, so choose the K-1 smallest remaining elements

The answer is the maximum of both cases. Each one’s score can be computed in \mathcal{O}(N), giving us a linear time solution.

Note that we need to be able to quickly find the sum of the K smallest elements that are not in A. This can be done by maintaining a mark array that denotes which elements are already in A, then iterating across it from 1 to 2N and adding i to the sum if mark[i] == 0.

TIME COMPLEXITY

\mathcal{O}(N) per test case.

CODE:

Tester's code (C++)
#include <bits/stdc++.h>
using namespace std;

int main() {
	int t;
	cin >> t;
	while(t--) {
	    int n, k;
	    cin >> n >> k;
	    long long int ans1 = 0, ans2 = 0;
	    int a[n];
	    for(int i = 0; i < n; i++) cin >> a[i];
	    sort(a, a + n);
	    vector<int> missing;
	    int now = 0;
	    for(int i = 1; i <= 2*n; i++) {
	        if(a[now] == i) now++;
	        else missing.push_back(i);
	    }
	    for(int i = 0 ; i < k ; i++) ans1 += max(0, a[n - 1] - missing[i]);
	    for(int i = 0 ; i < k - 1 ; i++) ans2 += max(0, 2*n - missing[i]);
	    cout << max(ans1, ans2) << "\n";
	}
	return 0;
}
Editorialist's code (Python)
for _ in range(int(input())):
    n, k = map(int, input().split())
    a = list(map(int, input().split()))
    mark = [0]*(2*n + 1)
    b = []
    for x in a:
        mark[x] = 1
    for i in range(1, 2*n+1):
        if mark[i] == 0:
            b.append(i)
    mx = max(a)
    ans = int(-10 ** 13)
    ans = max(ans, (k-1)*(2*n) - sum(b[0:k-1]))
    ans = max(ans, k*mx - sum(b[0:k]))
    print(ans)
3 Likes
#include <bits/stdc++.h>

#define ll long long
using namespace std;

int main() {
	cin.sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);
	ll int t;
	cin>>t;
	while(t--){
	    ll int n,k;
	    cin>>n>>k;
	    vector<ll int>v1,v2;
	    ll int arr[(2*n)+1] = {0};
	    for(ll int i=0; i<n; i++){
	        ll int temp = 0;
	        cin>>temp;
	        v1.push_back(temp);
	        arr[temp] = 1;
	    }
	    for(ll int i=1; i<=2*n; i++){
	        if(arr[i] == 0) v2.push_back(i);
	    }
	    sort(v1.begin(), v1.end());
	    ll int total=0;
	    ll int m=0, max = 2*n;
	    if(k==1) (v1[v1.size()-1]-v2[0])>0 ? total+= (v1[v1.size()-1]-v2[0]) : total+=0;
	    else{
	        if(v1[v1.size()-1] != max){
	            v1.push_back(max);
	            k--;
	        }
	        while(k--){
	            total+= (max-v2[m++]);
	        }
	    }
	    cout<<total<<'\n';
	}
	return 0;
}

My logic is same to editorial solution but why am I getting wrong answer for 3 test cases?

https://www.codechef.com/viewsolution/77015040

Why is my submission showing WA for 3 set of test cases?

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
ll M = 1e9+7;
#define REP(i, a, b) for (ll i = a; i <= b; ++i)
#define endl “\n”
#define pb push_back
#define mp make_pair
#define ff first
#define ss second

int main()
{

ll t=1;
cin>>t;
while(t--)
{
    ll n, k;
    cin>>n>>k;
    vector<ll> a;
    REP(i,0,n-1)
    {
        ll x;
        cin>>x;
        a.pb(x);
    }
    
    set<ll>s;
    REP(i,0,n-1)
    {
        s.insert(a[i]);
    }
    vector<ll> v1;
    for(ll i=1; i<=2*n; i++)
    {
        auto itr=s.find(i);
        if(itr==s.end())
            v1.push_back(i);
        else
            ;
    }
    ll sz=v1.size();
    // sort(v1.begin(),v1.end());
    if(v1[sz-1]==2*n)
    {
        k=k-1;
        ll sum=2*n*k;
        ll sum1=0;
        if(k==0)
            sum1=0;
            else{
        REP(i,0,k-1)
        {
            sum1= sum1+v1[i];
        }}
        sum= sum-sum1;
        cout<<sum<<endl;
        
    }
    else
    {
        ll sum=2*n*k;
        ll sum1=0;
        
        REP(i,0,k-1)
        {
            sum1=sum1+v1[i];
        }
        sum= sum-sum1;
        cout<<sum<<endl;
    }
    
}

}

https://www.codechef.com/viewsolution/77000417
My logic here is also same as the above solution , and I am getting WA in last 2 tasks . Please help. Am i missing some case where my solution doesn’t work ?

i found the smallest first missing number and sub it wit largest number why did it show WA ???

int firstMissingPositive(vector& nums) {
sort(nums.begin(),nums.end());
int ans=1;
for(int i=0;i<nums.size();i++)
{
if(nums[i]==ans)
ans++;
}
return ans;
}

int main() {
ll t; cin>>t;
while(t–){
ll n,k; cin>>n>>k;

    vector<int>arr(n);
    for(int i=0; i<n; i++){
        cin>>arr[i];
    }
    ll smallest = firstMissingPositive(arr);
    ll largest = 2*n;
    cout<<largest-smallest<<endl;
}
return 0;

}

1 Like

If K is 1 and 2*n is already available in the given array then only your solution will be right.

Consider this test case:
4 4
1 2 5 7

your tc –
4 4
1 2 5 7
lets take a variable max_value = 0;
and if diff[where diff is max(in array) - appended value]>max_value then max_value
Now, i take 8 and append it so max(in array) - 8 = 8 - 8 = 0 (k=4-1=3) max_value = 0
Now, i take 3 and append it so max(in array) - 3 = 8 - 3 = 5 (k=3-1=2) max_value = 5
Now ,i take 4 and append it so max(in array) - 4 = 8 - 4 = 4 (k=2-1) max_value = 5
Now , i take 6 and append it so max(in array)- 6 = 8 - 6 = 2(k=1-1=0) max_value = 5

so in conclusion max_value to be printed = 5
Or we can also conclude that k doesn’t play any role cause here asked to output max value which will the smallest next number which is not present in the array subtracted from 2*n,
every tc follows this…

@admin please check this toooooo, if I am wrong correct me.

The statement asks you to compute the maximum sum of scores, not the maximum score of a single move.

1 Like

The answer can exceed the range of int, use a 64-bit integer type like long long instead.

@ritesh_gupta97 @dunder
Consider the case

3 2
1 4 5

The answer is 5 (by appending 2 and 3 to the array, for a score of 5-2 + 5-3).

It’s not always optimal to first append 2n, that’s why the editorial takes the best answer out of two cases.

1 Like

ooh so i just need to add them ,while k-- instead of printing shit silly mistake :cry:

Thanks a lot , I can’t believe I missed such a small thing.

The answer goes beyond int limit. Use Long instead. Can’t believe I lost AC because of this.

1 Like

you’re not considering the case where max must be != 2*n, so you have in some cases a minor score. for example take:
case 1:
5 3
5 6 7 8 9,
inserting 1,2 and 3, the ans would be 9-1 + 9-2 + 9-3 = 21, but your program gives 17, since you are wasting a move inserting 10, whose score 10-10 is 0

1 Like

i know, the same here t.t