CXZ - Editorial

PROBLEM LINK:

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

Author: pols_agyi_pols
Tester: kingmessi
Editorialist: iceknight1093

DIFFICULTY:

TBD

PREREQUISITES:

None

PROBLEM:

There are N monsters, the i-th has health H_i.
You start with a strength of X, and can kill the i-th monster only if X\gt H_i.
After killing the i-th monster, your strength gets set to H_i.

At most once, you can multiply your strength by K.
Find the maximum number of monsters you can kill.

EXPLANATION:

First, let’s solve the problem if multiplication operation didn’t exist.

After killing a monster with health H_i, our strength gets set to H_i.
This means the next monster we kill must have a strength that strictly less than H_i.
The monsters we kill must thus have a strictly decreasing sequence of strengths.

The very first monster we kill must have a strength that’s less than X.
So, the maximum number of monsters that can be killed, is simply the number of distinct strengths less than X.


Now, let’s think about what the multiplication operation lets us do.
There are two possibilities: either we multiply right at the start, or we kill a few monsters and then multiply.

The first case is trivial: multiplying right at the start gives us a strength of X\cdot K, after which we can kill one monster for each distinct strength that’s less than X\cdot K.

The second case requires a bit more thought.
Suppose we multiply right after killing a monster with strength H_i, so that we’re now at a strength of K\cdot H_i.
Then,

  • We can certainly kill one monster for each distinct strength \lt K\cdot H_i.
  • We can also kill one monster for each distinct strength that’s \geq H_i and \lt X, on our initial path to reach H_i.
  • There is one caveat however: if there’s exactly one monster with strength Y, where both Y\lt K\cdot H_i and H_i \leq Y \lt X, then it should be counted once and not twice (since we can only kill it once).

So, for a fixed H_i being the last kill before multiplication, we want to know:

  1. The number of distinct elements that are \lt K\cdot H_i.
  2. The number of distinct elements that are \lt X and \geq H_i.
  3. The number of elements that appear exactly once, and are between H_i and \min(X, K\cdot H_i) - 1.

In the easy version, the constraints on K, H_i, X are fairly small (\leq 500), so you can compute these quantities by iterating over each value from 1 to 500 and checking which of the conditions it satisfies.
All you need to store is the frequency of each element.

TIME COMPLEXITY:

\mathcal{O}(500\cdot N) per testcase.

CODE:

Editorialist's code (Python)
for _ in range(int(input())):
    n, x, k = map(int, input().split())
    h = list(map(int, input().split()))
    freq = [0]*501
    for y in h: freq[y] += 1

    ans = 0
    # consider multiplying once at the start
    for y in range(1, 501):
        if y < x*k and freq[y] > 0: ans += 1
    
    for i in range(n):
        # multiply after killing h[i]
        # one copy of everything < h[i]*k
        # one copy of everything >= h[i] and < x
        # careful about stuff between h[i] and min(x, h[i]*k)

        ct = 0
        if h[i] >= x: continue
        for y in range(1, 501):
            if freq[y] == 0: continue

            if y < h[i]*k: ct += 1
            if y >= h[i] and y < x: ct += 1
            if freq[y] == 1 and y >= h[i] and y < min(x, h[i]*k): ct -= 1
        ans = max(ans, ct)
    
    print(ans)

Python editorial code will get tle with 2.5e8 operations

Why should we even consider the second case, of multiplying by K later rather than at the start? Wouldn’t KxX be always greater than KxHi, for any i. Is there any rule that says we have to go in order for defeating monsters?

Can somebody please put a testcase here, that shows case 2 is important as well

3 3 2
1 2 1

It does not when submitted in PyPy - in fact it runs in less than half the time limit.
(For competitive programming purposes, it’s almost always better to use PyPy over base Python.)

The number of elements that appear exactly once, and are between XiX_iXi​ and min⁡(X,K⋅Hi)−1\min(X, K\cdot H_i) - 1min(X,K⋅Hi​)−1.

I think it’s should be between H_i and min(X, K. H_i) -1.

code according to the editorial:= with comment and modularized functions

/*
    Author : Shaurya Singhal(jugshaurya)
    Date : 28-08-2024 T20
*/

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

#define int							 long long
#define endl						"\n"
#define IOS							ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);


vector<pair<int,int>> v;
vector<int> f1;

// right most index < x
int getIdxlessthan(int num){
    int lo = 0;
    int hi = v.size();
    hi--;
    int ans = -1;

    while(lo <= hi){
        int mid = (lo + hi)/2;

        if(v[mid].first < num){
            ans = mid;
            lo = mid + 1;
        } else {
            hi = mid - 1;
        }
    }

    return ans;
}

// #distinct < num -> logn
int no_of_distinct_less_than(int num){
    int lo = 0;
    int hi = v.size();
    hi--;
    int ans = -1;

    while(lo <= hi){
        int mid = (lo + hi)/2;

        if(v[mid].first < num){
            ans = mid;
            lo = mid + 1;
        } else {
            hi = mid - 1;
        }
    }

    return ans + 1;
}

// #distinct <= idx with freq == 1 -> logn
int no_of_distinct_with_f_1_before_equal(int idx){
    return f1[idx];
}

// #distinct <= idx with freq == 1 in range [a,b], both inclusive. -> logn
int no_of_distinct_with_f_1(int a, int b){
    return no_of_distinct_with_f_1_before_equal(b) - (a - 1 >= 0 ? no_of_distinct_with_f_1_before_equal(a - 1): 0);
}

void solve(int _i) {
    v.clear();
    f1.clear();

    int n,x,k;
    cin>>n>>x>>k;
    int arr[n];
    map<int,int> mp;
    for (int i = 0; i < n; i++) {
        cin>>arr[i];   
        mp[arr[i]]++;
    }

    for(auto x: mp){
        v.push_back({x.first, x.second});
        f1.push_back(x.second == 1);
        int l = f1.size();
        if(l - 2 >= 0) f1[l - 1] += f1[l - 2];
    } 

    // # distinct less than x*k;
    int ans = no_of_distinct_less_than(x * k);
    // right most index < x
    int idx = getIdxlessthan(x);

    if(idx < 0) {
        cout<<ans<<endl; 
        return;
    } else {
        for (int i = idx; i >= 0; i--) {
            // we have removed elements till i (including i).
            int nw = v[i].first * k;
            int cont = (idx - i + 1) + no_of_distinct_less_than(nw) - no_of_distinct_with_f_1(i, min(idx, getIdxlessthan(nw)));
            ans = max(ans, cont);
        }
    }

    cout<<ans<<endl;
}

signed main() {
    IOS
    int i = 1; 
    int _t; cin>>_t; for(;i<=_t;i++) 
    solve(i);
    return 0;
}

that testcase still does not show the need for second case in solution. U can multiply the initial X with K (or also choose not to multiply) and kill all monsters. We kill in order 2 1 1. Did I make any mistake here? Should it be in the order of given array elements?

There was no mention in the question that it should be in the order of array elements. The explanation for 3rd testcase can be ignored, because explanations can just be showing one of the possible ways, not the way. There was no clear indication that in order killing of monsters is necessary in the question.

Can you clarify my question please?? :pray: :pray: :pray:

Fixed the typo, thanks for pointing out.

Quoting the statement,

You can defeat the i-th monster if your current health X is strictly greater than the monster’s health H_i, i.e, if X\gt H_i.

The “strict” part is important here, you can’t kill 2 1 1 because after you kill the first 1, the second one isn’t strictly smaller anymore.