Codeforces Round 1133 (Div. 1, Div. 2) is coming soon! Register here. ×

shivankjha46's blog

By shivankjha46, 18 months ago, In English

Problem: MEX Sequence
time limit per test: 2 seconds
memory limit per test: 512 megabytes
You are given an array $$$a$$$ of length $$$n$$$. Define an infinite sequence $$$s$$$ as follows:
For $$$1 \leq i \leq n: s_i = a_i$$$
For $$$i \gt n$$$: $$$s_i$$$ = $$$\operatorname{mex}(s_{i-1}, s_{i-2}, ..., s_{i-n})$$$
You are given $$$q$$$ queries. In each query, you are given an integer $$$k$$$, and you have to determine $$$s_k$$$.
Input
Each test contains multiple test cases. The first line contains a single integer $$$t$$$ $$$(1 \leq t \leq 10^4)$$$, the number of test cases. The description of the test cases follows.
The first line of each test case contains two integers $$$n$$$ and $$$q$$$ $$$(1 \leq n, q \leq 2 \cdot 10^5)$$$, the size of the array and the number of queries, respectively.
The second line of each test case contains $$$n$$$ integers $$$a_1, a_2, ..., a_n$$$ $$$(0 \leq a_i \leq n)$$$ — the elements of the array $$$a$$$.
The third line of each test case contains $$$q$$$ integers $$$k_1, k_2, ..., k_q$$$ $$$(1 \leq k_i \leq 10^{18})$$$, where $$$k_i$$$ is the value of $$$k$$$ for the $$$i$$$-th query.
It's guaranteed that the sum of $$$n$$$ and the sum of $$$q$$$ over all test cases does not exceed $$$2 \cdot 10^5$$$.
Output
For each test case, output a line with $$$q$$$ integers, where the $$$i$$$-th integer is the answer to the $$$i$$$-th query.

Please try to solve the question first before seeing the solution unless you're new!
If you get stuck, I recommend you see this problem from CSES then solve this one.
Feel free to rate the problem from 1 to 10!
Update: Shoutout to BLOBVISGOD to be the first solver of the problem!
Update: The editorial is here!

Solution
  • Vote: I like it
  • +11
  • Vote: I do not like it

| Write comment?
»
18 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

If k>2N then its easy to solve it with a formula otherwise you can just bruteforce first 2N elements before the queries and output a[K]

  • »
    »
    18 months ago, hide # ^ |
     
    Vote: I like it +9 Vote: I do not like it

    How does your "easy" formula work, and how do you brute force efficiently (n=1e5)?

    My solution is as follows: First observe that s_{i+1},...,s_{i+n} cannot be equal to s_{i}, and furthermore for i>n, we have s_{i} <= n, since it is the mex of n numbers. Hence for i>n, the sequence is periodic with period n+1, and s_{n+1},...,s_{2n+2} are a permutation of 0,...,n.

    To find this permutation, we can use an std::set that stores the numbers from 0,...,n that do not occur in our 'current' window of n elements. we can find the MEX by doing *set.begin(), and update the set by adding numbers s_{i-n} to it if it is the last occurrence of s_{i-n} in the interval, and removing s_{i} from the set, since after the interval moves one place to the right it will contain s_{i}.

    I am not sure if there is an easier way? what is your solution?

    • »
      »
      »
      18 months ago, hide # ^ |
       
      Vote: I like it +8 Vote: I do not like it

      Use ordered set and binary search for the first value i such that order_of_key(i) doesnt equal i and then you know the mex is i. Now you continue this until all values from 0-N are filled then you will notice that the Mex will just increase by one each time

»
18 months ago, hide # |
 
Vote: I like it 0 Vote: I do not like it

Come on! Please give a code solution quickly. I'll only count that. Hopefully you give one in C++ so that I can understand your code since I don't do Python and other languages.

  • »
    »
    18 months ago, hide # ^ |
     
    Vote: I like it +1 Vote: I do not like it

    aight, calm down:

    #include "bits/stdc++.h"
    using namespace std;
    #define rep(i,a,b) for(int i=(a); i<(b); ++i)
    typedef long long ll;
    typedef vector<int> vi;
    
    void solve(){
        int n,q; cin >> n >> q;
        vi a(n), cnt(n+1), perm(n+1);
        for(auto& c : a) cin >> c;
        set<int> missing;
        rep(i,0,n) if (a[i]<=n) cnt[a[i]]++;
        rep(i,0,n+1) if (cnt[i]<1) missing.insert(i);
        rep(i,0,n+1){
            perm[i] = *begin(missing);
            missing.erase(perm[i]);
            cnt[perm[i]]++;
            if (i<n) {
                cnt[a[i]]--;
                if (cnt[a[i]]<1) missing.insert(a[i]);
            }
        }
        while(q--){
            ll x; cin >> x; --x;
            if (x<n) cout << a[x] << '\n';
            else cout << perm[(x-n)%(n+1)] << '\n';
        }
    }
    
    int main(){
        cin.tie(NULL),cin.sync_with_stdio(false);
        
        int t; cin >> t;
        while(t--) solve();
    }
    
    
  • »
    »
    18 months ago, hide # ^ |
    ← Rev. 2  
    Vote: I like it 0 Vote: I do not like it

    Following is my approach: Simply find the MEX of the initial array, and that will be the element at the (n)th index (0-based) , these elements keep repeating, therefore element at index k is the same as the element at index k%(n+1)

    /* Coded by harshcooljn */
    
    #include <bits/stdc++.h>
    #include <iostream>
    #include <stdint.h>
    #include <ios>
    #include <iomanip>
    #include <numeric>
    #include <math.h>
    #include <vector>
    #include <stdlib.h>
    #include <queue>
    #include <utility>
    #include <map>
    #include <set>
    #include <unordered_set>
    #include <unordered_map>
    #include <algorithm>
    #include <string>
    using namespace std;
    typedef long long int ll;
    typedef long double ld;
    typedef unsigned long long int ull;
    typedef pair<ll, ll> pll;
    #define vll vector<ll>
    #define vstr vector<string>
    #define vvll vector<vector<ll> >
    #define vpll vector<pair<ll,ll> >
    #define endl '\n'
    #define vin(v,a,n) for(ll i=a;i<n;i++){cin>>v[i];}
    #define vinp(v,n) for(ll i=0;i<n;i++){ll x;cin>>x;v.push_back(x);}
    #define pvec(v) for(auto &e: v){cout << e << " ";}cout<<endl;
    #define pvecp(v) for (ll i=0;i<v.size();i++){cout << v[i].first << "," << v[i].second << " \n"[i==v.size()-1];}
    #define parr(a,n) for(ll i=0;i<n;i++){cout << a[i] << "";}
    #define parr1(a,n) for(ll i=1;i<=n;i++){cout << a[i] << "";}
    #define yes cout<<"YES"<<endl;
    #define full(v) v.begin(),v.end()
    #define fr(i,a,n) for(ll i=a;i<n;i++)
    #define fr_(i,n,a) for (ll i=n;i>=a;i--)
    #define no cout<<"NO"<<endl;
    #define spc ' '
    #define nline cout<<endl;
    #define fileIO freopen("input.txt","r",stdin);freopen("output.txt","w",stdout)
    #define fastIO ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0)
    
    
    void Solve(ll t10) {
        ll n,q;
        cin >> n >> q;
        vll a(n+1);
        set<ll> st;
        fr(i,0,n+1){
            st.insert(i);
        }
        fr(i,0,n){
            cin >> a[i];
            st.erase(a[i]);
        }
        a[n] = *st.begin(); // this is the mex of elements from [0,n-1] (0 - based index)
        while (q--){
            ll k;
            cin >> k;
            k--;
            cout << a[k%(n+1)] << " ";
        }
        cout << endl;
    }
    
    int main() {
        fastIO;
        // fileIO;
        ll t;cin >> t;fr(c, 1, t + 1) Solve(c);
        // Solve(1);
        return 0;
    }
    
    

    UPD : I assumed that the elements were distinct , my bad

»
18 months ago, hide # |
← Rev. 2  
Vote: I like it 0 Vote: I do not like it

I have a solution that solves for arbitrarily large $$$A_i$$$, of course if $$$A_i$$$ is like $$$\le 10^{100}$$$ then we got to do bignum calculation and it would be really annoying. If $$$k \le n$$$ we simple output $$$A_n$$$. Otherwise, WLOG, supposed $$$A$$$ is sorted, then $$$S_{n + 1 + [0, A_1)}$$$ would be $$$[0, A_1)$$$, and $$$S_{n + [A_1, A_2 - 1)}$$$ would be $$$[A_1 + 1, A_2)$$$, and so on.

  • »
    »
    18 months ago, hide # ^ |
     
    Vote: I like it 0 Vote: I do not like it

    Also, you will lose generality because the sequence values depend on the last $$$n$$$ terms which may not necessarily be sorted. Thus, the WLOG part is also wrong according to me.

    • »
      »
      »
      18 months ago, hide # ^ |
       
      Vote: I like it 0 Vote: I do not like it

      Oh sorry, I didn't read the statement carefully. It says $$$S_i$$$ is the MEX of last $$$n$$$ terms, not all the previous terms. Otherwise my solution would be correct. Sorry about that man. If so then we can just maintain a set to track the missing element from $$$0$$$ to $$$n - 1$$$, and compute the smallest one for each element from $$$n + 1$$$ to $$$2n$$$.

»
18 months ago, hide # |
 
Vote: I like it +3 Vote: I do not like it

you are 12 years old ?!!!