PROBLEM LINK:
Practice
Contest: Division 1
Contest: Division 2
Contest: Division 3
Contest: Division 4
Author: pols_agyi_pols
Tester: kingmessi
Editorialist: iceknight1093
DIFFICULTY:
Simple
PREREQUISITES:
None
PROBLEM:
You’re given an array A. In one move, you can delete either a prefix or a suffix of A, as long as A doesn’t become empty.
Find the minimum number of moves needed to make K the most frequent element of A.
It’s guaranteed that A contains K.
EXPLANATION:
Since K appears in A, the answer is definitely at most 2: let i be an index such that A_i = K, then on the first move we can delete everything before i, and on the second move everything after i, leaving K as the only element in A.
This means we need to check if the answer can possibly be 0 or 1.
Checking if the answer is 0 is easy: no moves can be made, so K must already be the most frequent element in A.
Compute the frequencies of every element and check if \text{freq}[K] is the maximum among them.
This leaves checking for the answer being 1.
In one move, we can delete either a prefix or a suffix - equivalently, we’ll leave either a prefix or a suffix.
So, all that needs to be checked is whether K is the most frequent element in some prefix or some suffix.
This can be done as follows, for the prefix (suffix is similar, just reverse the array and run the same algorithm):
- Define \text{freq}[i][x] to be the frequency of x among the first i elements of A.
- This can be computed as follows:
- \text{freq}[i][A_i] = 1 + \text{freq}[i-1][A_i]
- \text{freq}[i][x] = \text{freq}[i-1][x] for each x \neq A_i
Since A_i \leq 20, all these values can be computed in \mathcal{O}(20\cdot N) time.
Then, check if there exists an i such that \text{freq}[i][K] \geq \text{freq}[i][x] for every x - if yes then the answer can be 1.
As noted above, this algorithm should be run on both the prefix and suffix to check if the answer can be 1.
If the checks for both 0 and 1 fail, the answer will be 2 instead.
TIME COMPLEXITY:
\mathcal{O}(20\cdot N) per testcase.
CODE:
Author's code (C++)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
ll kitne_cases_hain;
kitne_cases_hain=1;
cin>>kitne_cases_hain;
while(kitne_cases_hain--){
ll n,k;
cin>>n>>k;
ll a[n+1];
ll cnt[n+1][21];
for(int i=1;i<=20;i++){
cnt[0][i]=0;
}
for(int i=1;i<=n;i++){
cin>>a[i];
for(int j=1;j<=20;j++){
cnt[i][j]=cnt[i-1][j];
}
cnt[i][a[i]]++;
}
ll flag=0;
for(int i=1;i<=20;i++){
if(cnt[n][i]>cnt[n][k]){
flag=1;
break;
}
}
if(!flag){
cout<<"0\n";
continue;
}
flag=0;
for(int i=1;i<=n;i++){
flag=1;
for(int j=1;j<=20;j++){
if(cnt[i][j]>cnt[i][k]){
flag=0;
break;
}
}
if(flag){
cout<<"1\n";
break;
}
flag=1;
for(int j=1;j<=20;j++){
if((cnt[n][j]-cnt[i-1][j])>(cnt[n][k]-cnt[i-1][k])){
flag=0;
break;
}
}
if(flag){
cout<<"1\n";
break;
}
}
if(!flag){
cout<<"2\n";
}
}
return 0;
}
Editorialist's code (PyPy3)
def check(a, k):
freq = [0]*21
ret = 2
for x in a:
freq[x] += 1
if freq[k] == max(freq): ret = 1
if freq[k] == max(freq): ret = 0
return ret
for _ in range(int(input())):
n, k = map(int, input().split())
a = list(map(int, input().split()))
print(min(check(a, k), check(a[::-1], k)))