题目概述

原题参考: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问题,可以使用并查集求解

posted on 2024-03-06 19:17  山余木  阅读(50)  评论(0)    收藏  举报