並查集解mex_cf932_B. Informatics in MAC

山余木發表於2024-03-06

目錄
  • 題目概述
  • 思路想法
  • 參考程式碼
  • 做題反思

題目概述

原題參考:B. Informatics in MAC
給出一個長度為n的陣列,問是否可以將其分為k個(k>1)mex相同的陣列,如果可以的話,作出一種劃分

思路想法

假設一個陣列可以被分為k(k>2)個區間,每個區間的mex相同,那麼可以確定的是,該陣列中一定不存在mex這個數,假設存在mex,那麼mex無論劃分到任意區間,那麼該區間的mex都不可能是mex;因此,我們可以知道陣列中不存在mex元素,因此假如可以將陣列劃分為k(k>2)個區間,那麼也可以將陣列劃分為2個區間,這兩個區間的mex相同,那麼只需要對陣列分別正向和逆向求一遍mex即可
如何快速的求mex,已知mex是一段區間中未出現的最小正整數,也就是說,可以將該區間分為兩部分(以上),也就是說,該區間是不連續的,求解連續性問題,很容易想到並查集,那麼對於並查集的初始化就是每個點只能連結自己,當出現某一點時,可以知道,mex不可能是她,也就是說,他和下一位連結起來了,對於每次求當前區間的mex,只需要找到從0開始的最遠的區間即可

參考程式碼

#include <bits/stdc++.h>
using namespace std;
#define FAST_IO ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl '\n'
#define pll pair<long long, long long>
#define pii pair<int, int>
#define vi vector<int>
#define vl vector<long long>
#define ll long long
#define ull unsigned long long
const ll INF = 9187201950435737471;
const int inf = 2139062143;
const ll mod = 1e9 + 7;
const double eps = 1e-6;
const double PI = acos(-1.0);
const int N = 2e5+7;
int n, a[N], mmax = 0;
struct DSU {
    int fa[N];
    DSU(int n) {for(int i=0; i<=n; i++) fa[i] = i;}
    void init(int n) {for(int i=0; i<=n; i++) fa[i] = i;}
    int find(int x) {
        if(fa[x] == x) return x;
        return fa[x] = find(fa[x]);
    }
};
void solve() {
    int lt[N], rt[N];
    cin >> n;
    for(int i=1; i<=n; i++) cin >> a[i], mmax = max(mmax, a[i]);
    DSU k(mmax+5);
    for(int i=1; i<=n; i++) {
        k.fa[a[i]] = k.find(a[i]+1);
        lt[i] = k.find(0);
    }
    k.init(mmax+5);
    for(int i=n; i; i--) {
        k.fa[a[i]] = k.find(a[i]+1);
        rt[i] = k.find(0);
    }
    int ans = -1;
    for(int i=1; i<=n-1; i++) {
        if(lt[i] == rt[i+1]) {
            ans = i;
            break;
        }
    }
    cout << (ans == -1 ? -1 : 2) << endl;
    if(ans != -1) cout << 1 << " " << ans << endl << ans+1 << " " << n << endl; 
}
int main() {
#ifdef xrl
    freopen("in.txt", "r", stdin), freopen("out.txt", "w", stdout);
#endif
    FAST_IO;
    int t = 1;
    cin >> t;
    while(t --) solve();
#ifdef xrl
    cout << "Time used = " << (double)(clock() * 1.0 / CLOCKS_PER_SEC) << "s";
#endif
    return 0;
}

做題反思

去接靜態mex問題,可以使用並查集求解

相關文章