题目链接:https://ac.nowcoder.com/acm/contest/5673/A
直接线段树维护每一个关系的生命周期,加一个带撤销并查集,然后dfs更新答案就行了
题目倒是不难写,mark一个带撤销并查集的板子
代码:
#include<bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int MAXN=2e5+5;
map<pii,int> last;
int cnt[MAXN<<1],used[MAXN<<1];
struct UFS
{
stack<pair<int*, int>> stk;
int fa[MAXN<<1],rnk[MAXN<<1];
inline void init(int n)
{
for(int i=0;i<=n;i++) fa[i]=i,rnk[i]=0;
}
inline int Find(int x)
{
while(x^fa[x]) x=fa[x];
return x;
}
inline bool Merge(int x,int y)
{
x=Find(x),y=Find(y);
if(x==y) return false;
if(rnk[x]<=rnk[y])
{
stk.push({fa+x,fa[x]});
fa[x]=y;
if(rnk[x]==rnk[y])
{
stk.push({rnk+y,rnk[y]});
rnk[y]++;
}
}
else
{
stk.push({fa+y,fa[y]});
fa[y]=x;
}
return true;
}
inline void Undo()
{
*stk.top().xx=stk.top().yy;
stk.pop();
}
}dsu;
struct seg
{
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
vector<pii> tr[MAXN<<2];
int cover,num,player;
void init(int n,int m)
{
cover=m;player=n;num=n+m;
}
void update(int L,int R,pii val,int l,int r,int rt)
{
if(L>R) return ;
if(L<=l&&r<=R)
{
tr[rt].pb(val);
return ;
}
int mid=(l+r)>>1;
if(L<=mid)
update(L,R,val,lson);
if(mid<R)
update(L,R,val,rson);
}
void doit(int rt)
{
for(auto it:tr[rt])
{
if(!cnt[it.xx]) cover--;
if(!used[it.yy]) player--;
cnt[it.xx]++;
used[it.yy]++;
if(dsu.Merge(it.xx,it.yy)) num--;
}
}
void undo(int rt,int sz,int prenum)
{
num=prenum;
for(auto it:tr[rt])
{
cnt[it.xx]--;
used[it.yy]--;
if(!cnt[it.xx]) cover++;
if(!used[it.yy]) player++;
}
int now=dsu.stk.size();
while(now>sz)
{
dsu.Undo();
now--;
}
}
void dfs(int l,int r,int rt)
{
int sz=dsu.stk.size();
int prenum=num;
doit(rt);
if(l==r)
printf("%d\n",cover==0?num-player:-1);
if(l!=r)
{
int mid=(l+r)>>1;
dfs(lson);
dfs(rson);
}
undo(rt,sz,prenum);
}
}se;
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
int n,m,q;
scanf("%d%d%d",&n,&m,&q);
dsu.init(n+m);
se.init(n,m);
for(int i=1;i<=n;i++)
{
int k;
scanf("%d",&k);
for(int j=1;j<=k;j++)
{
int x;
scanf("%d",&x);
last[{x,m+i}]=1;
}
}
for(int i=1;i<=q;i++)
{
int x,y;
scanf("%d%d",&x,&y);
y+=m;
if(last[{x,y}])
{
int &pos=last[{x,y}];
se.update(pos,i-1,{x,y},1,q,1);
pos=0;
}
else
{
last[{x,y}]=i;
}
}
for(auto it:last)
if(it.yy)
se.update(it.yy,q,it.xx,1,q,1);
se.dfs(1,q,1);
return 0;
}