從CF1935B學習維護前字尾區間mex

加固文明幻景發表於2024-03-10

Problem - B - Codeforces

維護字首區間mex和字尾區間mex,列舉二者相同的斷點

原理

隨區間增長,\(\texttt{mex}\) 只可能增,不可能減,所以可以用一個變數維護目前的 \(mex\),區間擴大後可以直接沿用較小區間的 \(mex\),再處理增加即可。

維護 \(\texttt{mex}\)

std::set<int> S;//當前集合內的元素
int mex(0);//當前mex
for (int i = l; i < r; i++) {
	S.insert(a[i]);
    while(S.contains(mex)) {
		mex++;
    }
}

程式碼

void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (auto& x : a) std::cin >> x;
    std::set<int> preS, sufS;
    std::vector<int> pre(n), suf(n);
    int preMex(0), sufMex(0);
    for (int i = 0; i < n; i++) {
        preS.insert(a[i]);
        while(preS.contains(preMex)) {
            preMex++;
        }
        pre[i] = preMex;
    }
    for (int i = n - 1; i >= 0; i--) {
        sufS.insert(a[i]);
        while(sufS.contains(sufMex)) {
            sufMex++;
        }
        suf[i] = sufMex;
    }
    for (int i = 0; i < n; i++) {
        if (pre[i] == suf[i + 1]) {
            std::cout << 2 << '\n';
            std::cout << 1 << ' ' << i + 1 << '\n';
            std::cout << i + 1 + 1 << ' ' << n << '\n';
            return ; 
        }
    }
    error; return ;
}

相關文章