离线之后把删数变成加数, 然后一边跑匈牙利一遍算答案。
#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; } /* */