Submission #1353044

#TimeUsernameProblemLanguageResultExecution timeMemory
1353044Alex1298Equalmex (CEOI25_equalmex)C++20
67 / 100
2096 ms69432 KiB
#include <iostream>
#include <vector>
#include <cmath>

using namespace std;

struct Node
{
    int minpoz;
    int st, dr;
};

struct Query
{
    int left, right, ind;
};

int n, q;
int cnt;
int v[600005];
pair<int, int> qs[600005];
Node pool[5000005];
int root[600005];
vector<Query> qs_mex[400005];
int bin[23][600005];

void update(int cur, int prev, int left, int right, int poz, int val)
{
    if(left == right)
    {
        pool[cur].minpoz = val;
        return;
    }

    int mij = (left + right) / 2;
    if(poz <= mij)
    {
        cnt++;
        pool[cur].st = cnt;
        pool[pool[cur].st] = pool[pool[prev].st];

        pool[cur].dr = pool[prev].dr;

        update(pool[cur].st, pool[prev].st, left, mij, poz, val);
    }
    else
    {
        cnt++;
        pool[cur].dr = cnt;
        pool[pool[cur].dr] = pool[pool[prev].dr];

        pool[cur].st = pool[prev].st;

        update(pool[cur].dr, pool[prev].dr, mij+1, right, poz, val);
    }

    pool[cur].minpoz = min(pool[pool[cur].st].minpoz, pool[pool[cur].dr].minpoz);
}

int find_mex(int node, int left, int right, int st)
{
    if(left == right)
    {
        return left;
    }

    int mij = (left + right) / 2;
    if(pool[pool[node].st].minpoz < st)
    {
        return find_mex(pool[node].st, left, mij, st);
    }
    else
    {
        return find_mex(pool[node].dr, mij+1, right, st);
    }
}

int query(int node, int left, int right, int qleft, int qright)
{
    if(qright < left || right < qleft)
    {
        return n + 1;
    }

    if(qleft <= left && right <= qright)
    {
        return pool[node].minpoz;
    }

    int mij = (left + right) / 2;
    return min(query(pool[node].st, left, mij, qleft, qright),
               query(pool[node].dr, mij+1, right, qleft, qright));
}

std::vector<int> solve(int N, std::vector<int> &init, int Q, std::vector<std::pair<int, int>> &initqs)
{
    n = N;
    q = Q;

    for(int i = 0; i<n; i++)
    {
        v[i + 1] = init[i];
    }
    for(int i = 0; i<q; i++)
    {
        qs[i + 1] = initqs[i];
        qs[i + 1].first++;
        qs[i + 1].second++;
    }

    for(int i = 1; i<=n; i++)
    {
        cnt++;
        root[i] = cnt;

        update(root[i], root[i - 1], 1, 4e5, v[i], i);
    }

    vector<int> rez;
    rez.resize(q);

    for(int i = 1; i<=q; i++)
    {
        int mex = find_mex(root[qs[i].second], 1, 4e5, qs[i].first);
        if(mex == 1)
        {
            rez[i - 1] = qs[i].second - qs[i].first + 1;
            continue;
        }

        qs_mex[mex].push_back({qs[i].first, qs[i].second, i});
    }

    int SQ = sqrt(n);
    int LG = log2(n);

    for(int i = 2; i<=n + 1; i++)
    {
        if(qs_mex[i].size() == 0)
        {
            continue;
        }

        if(i > SQ)
        {
            for(auto it: qs_mex[i])
            {
                int ans = 0;
                int cur = it.right;
                while(cur >= it.left)
                {
                    int nxt = query(root[cur], 1, 4e5, 1, i - 1);
                    if(nxt < it.left)
                    {
                        break;
                    }

                    ans++;
                    cur = nxt - 1;
                }

                rez[it.ind - 1] = ans;
            }
        }
        else
        {
            for(int j = 1; j<=n; j++)
            {
                bin[0][j] = query(root[j], 1, 4e5, 1, i - 1);
            }

            for(int k = 1; k <= LG; k++)
            {
                for(int j = 1; j<=n; j++)
                {
                    if(bin[k - 1][j] == 0)
                    {
                        bin[k][j] = 0;
                    }
                    else
                    {
                        bin[k][j] = bin[k - 1][bin[k - 1][j] - 1];
                    }
                }
            }

            for(auto it: qs_mex[i])
            {
                int ans = 0;
                int poz = it.right;

                for(int bit = LG; bit>=0; bit--)
                {
                    if(bin[bit][poz] >= it.left)
                    {
                        ans += (1 << bit);
                        poz = bin[bit][poz] - 1;
                    }
                }

                rez[it.ind - 1] = ans;
            }
        }
    }

    return rez;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...