Submission #1338938

#TimeUsernameProblemLanguageResultExecution timeMemory
1338938Zero_OPEqualmex (CEOI25_equalmex)C++20
100 / 100
921 ms238856 KiB
#include <bits/stdc++.h>

using namespace std;

#define FOR(i, l, r) for(int i = (l); i < (r); ++i)
#define F0R(i, r) FOR(i, 0, r)
#define FORD(i, l, r) for(int i = (r) - 1; i >= (l); --i)
#define F0RD(i, r) FORD(i, 0, r)
#define all(v) begin(v), end(v)
#define rall(v) rbegin(v), rend(v)
#define sz(v) (int)v.size()
#define pb push_back 
#define eb emplace_back
#define uniquify(v) v.erase(unique(all(v)), end(v))
#define ff first
#define ss second
#define mp make_pair 
#define mt make_tuple 
#define dbg(x) "[" #x " = " << (x) << "]"
#define tcT template<class T 
tcT> bool minimize(T& a, const T& b){ return a > b ? a = b, 1 : 0; }
tcT> bool maximize(T& a, const T& b){ return a < b ? a = b, 1 : 0; }
tcT> using vc = vector<T>;
tcT> using vvc = vc<vc<T>>;
using ll = long long;
using db = double;
using pi = pair<int, int>;
using pl = pair<ll, ll>;
using vi = vc<int>;
using vl = vc<ll>;
using vpi = vc<pi>;
using vpl = vc<pl>;
using vvi = vvc<int>;
using vvl = vvc<ll>;
using vvpi = vvc<pi>;
using vvpl = vvc<pl>;

#define ls (lc[s])
#define rs (rc[s])
const int MAX = 1e6 + 5;
const int MAXNODES = MAX * 20;

int nodes, lc[MAXNODES], rc[MAXNODES], minpos[MAXNODES];

int createNode(){
	++nodes;
	return nodes;
}	

void pull(int s){
	minpos[s] = min(minpos[ls], minpos[rs]);
}

int update(int s, int l, int r, int pos, int val){
	if(l == r){
		int ns = createNode();
		minpos[ns] = val;
		return ns;
	} else{
		int mid = l + r >> 1, ns = createNode();	
		lc[ns] = ls;
		rc[ns] = rs;
		if(pos <= mid) lc[ns] = update(ls, l, mid, pos, val);
		else rc[ns] = update(rs, mid + 1, r, pos, val);
		pull(ns);
		return ns;
	}
}

int query(int s, int l, int r, int bound){
	if(l == r) return l;
	int mid = l + r >> 1;
	if(minpos[ls] < bound) return query(ls, l, mid, bound);
	return query(rs, mid + 1, r, bound);
}

vi solve(int N, vi& _A, int Q, vpi& queries){
	vi A(N + 1);
	int bound = 0;
	F0R(i, N) maximize(bound, A[i + 1] = min(_A[i], N + 1));
	++bound;
	F0R(i, Q){
		++queries[i].ff, ++queries[i].ss;
	}

	vi ans(Q), ver(N + 1);
	for(int i = 1; i <= N; ++i){
		ver[i] = update(ver[i - 1], 1, bound, A[i], i);
	}
	
	auto findMex = [&](int l, int r){
		return query(ver[r], 1, bound, l);
	};

	vvi queriesByMex(N + 2);
	F0R(i, Q){
		auto [L, R] = queries[i];
		int mex = findMex(L, R);
		if(mex == 1){
			ans[i] = R - L + 1;
		}  else{
			queriesByMex[mex].eb(i);
		}
	}

	vvi positionsByValue(N + 2);
	FOR(i, 1, N + 1) positionsByValue[A[i]].eb(i);

	auto findNext = [&](int x, int from){ //from < pos
		int pos = upper_bound(all(positionsByValue[x]), from) - positionsByValue[x].begin();
		return pos == sz(positionsByValue[x]) ? -1 : positionsByValue[x][pos];
	};

	auto findPrevious = [&](int x, int to){ //pos < to
		int pos = lower_bound(all(positionsByValue[x]), to) - positionsByValue[x].begin();
		return pos == 0 ? -1 : positionsByValue[x][pos - 1];
	};

	//find minimum mex intervals
	vvpi minimumMexIntervals(N + 2);
	FOR(i, 1, N + 1){
		if(A[i] == 1){
			minimumMexIntervals[2].eb(i, i);
		}
	}

	for(int mex = 2; mex <= N + 1; ++mex){
		vpi& intervals = minimumMexIntervals[mex];
		sort(all(intervals));
		F0R(i, sz(intervals)){
			auto [l, r] = intervals[i];
			int x = findPrevious(mex, l);
			if(x != -1 && (i == 0 || (intervals[i - 1].ss < x))){
				int newMex = findMex(x, r);
				assert(mex < newMex);
				minimumMexIntervals[newMex].eb(x, r);
			}

			int y = findNext(mex, r);
			if(y != -1 && (i + 1 == sz(intervals) || (intervals[i + 1].ff > y))){
				int newMex = findMex(l, y);
				assert(mex < newMex);
				minimumMexIntervals[newMex].eb(l, y);
			}
		}

		if(!queriesByMex[mex].empty()){
			const int B = 18;
			int siz = sz(intervals);
			vector<array<int, B>> jump(siz);
			int ptr = 0;
			F0R(i, siz){
				++intervals[i].ss;
				while(ptr < siz && intervals[i].ss > intervals[ptr].ff) ++ptr;
				jump[i][0] = ptr;
			}

			F0RD(i, siz){
				FOR(j, 1, B){
					if(jump[i][j - 1] == siz){
						jump[i][j] = siz;
					} else{
						jump[i][j] = jump[jump[i][j - 1]][j - 1];
					}
				}
			}

			for(auto id : queriesByMex[mex]){
				auto [L, R] = queries[id];
				++R;

				int u = lower_bound(all(intervals), mp(L, -1)) - intervals.begin();
				if(u < siz) F0RD(i, B){
					if(jump[u][i] != siz && intervals[jump[u][i]].ss <= R){
						ans[id] += (1 << i);
						u = jump[u][i];
					}
				}
				if(u < siz && intervals[u].ss <= R) ++ans[id];
			}
		}
	}
	return ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...