Maximize Mex

离线之后把删数变成加数, 然后一边跑匈牙利一遍算答案。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define PLL pair<LL, LL>
#define PLI pair<LL, int>
#define PII pair<int, int>
#define SZ(x) ((int)x.size())
#define ull unsigned long long

using namespace std;

const int N = 5000 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double PI = acos(-1);

int n, m;
int p[N], c[N];
int d, match[N];
bool vis[N];
bool ban[N];

vector<int> person;
vector<int> G[N];
vector<int> ans;

int path(int u) {
    for(auto& v : G[u]) {
        if(!vis[v]) {
            vis[v] = true;
            if(match[v] == -1 || path(match[v])) {
                match[v] = u;
                return 1;
            }
        }
    }
    return 0;
}

int main() {
    memset(match, -1, sizeof(match));
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%d", &p[i]);
    for(int i = 1; i <= n; i++) scanf("%d", &c[i]);
    scanf("%d", &d);
    for(int i = 1; i <= d; i++) {
        int who; scanf("%d", &who);
        ban[who] = true;
        person.push_back(who);
    }
    for(int i = 1; i <= n; i++) {
        if(ban[i]) continue;
        G[p[i]].push_back(c[i]);
    }
    for(int i = SZ(person) - 1, j = 0; i >= 0; i--) {
        while(1) {
            memset(vis, 0, sizeof(vis));
            if(path(j)) j++;
            else break;
        }
        int x = person[i];
        ans.push_back(j);
        G[p[x]].push_back(c[x]);
    }
    reverse(ans.begin(), ans.end());
    for(auto& x : ans) printf("%d\n", x);
    return 0;
}

/*
*/