Solution
我们离线然后倒着插入边,那么答案就是不降的了
考虑对p和c建二分图,一个人就连一条边,那么跑匈牙利就可以了
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define drp(i,st,ed) for (int i=st;i>=ed;--i)
const int INF=0x3f3f3f3f;
const int N=200005;
const int E=500005;
struct edge {int x,y,next;} e[E];
int ls[N],r[N],v[N],p[N],c[N],edCnt;
int link[N],vis[N],prt[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):(v),ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void add_edge(int x,int y) {
e[++edCnt]=(edge) {x,y,ls[x]}; ls[x]=edCnt;
e[++edCnt]=(edge) {y,x,ls[y]}; ls[y]=edCnt;
}
int find(int x,int id) {
for (int i=ls[x];i;i=e[i].next) {
if (vis[e[i].y]==id) continue;
vis[e[i].y]=id;
if (!link[e[i].y]||find(link[e[i].y],id)) {
link[e[i].y]=x;
return 1;
}
}
return 0;
}
int main(void) {
int n=read(),m=read();
rep(i,1,n) p[i]=read();
rep(i,1,n) c[i]=read();
int d=read();
rep(i,1,d) {
r[i]=read();
v[r[i]]=1;
}
rep(i,1,n) if (!v[i]) {
add_edge(n+p[i]+1,c[i]);
}
int ans=0,wjp=1;
drp(i,d,1) {
for (;find(n+ans+1,++wjp);) ans++;
prt[i]=ans;
add_edge(n+p[r[i]]+1,c[r[i]]);
}
rep(i,1,d) printf("%d\n", prt[i]);
return 0;
}