思路:
由题可以得到一个结论:fans和player组成的联通快只需要一个player就可以让这个联通快内所有fans都满足条件。
那就直接把每个关系当成一个边,按时间建线段树,用可撤销并查集,维护图的连通性即可。
对于有单独的fans组成一个联通快的显然无解了。。
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 5e5 + 10;
#define fi first
#define se second
#define pb push_back
#define wzh(x) cerr<<#x<<'='<<x<<endl;
int n,m,q;
vector<pair<int,int>>v[N<<2];
#define mid (l+r>>1)
#define ls o<<1
#define rs o<<1|1
void ins(int o,int l,int r,int x,int y,int dx,int dy){
if(l>=x&&r<=y){
v[o].emplace_back(dx,dy);
return;
}
if(x<=mid)ins(ls,l,mid,x,y,dx,dy);
if(y>mid)ins(rs,mid+1,r,x,y,dx,dy);
}
set<pair<int,int> >g[N];
int tot=0;
int st[N],f[N],sz[N],cn[N],co[N];
int find(int x){
while(f[x]!=x){
x=f[x];
}
return x;
}
int now;
int sum,tim;
//一个联通快 只需要一个player...
int need[N];
void merge(int x,int y){
int dx=find(x),dy=find(y);
if(dx==dy)
return;
if(sz[dx]>sz[dy])swap(dx,dy);
if(sz[dx]==1&&dx<=n)need[dx]=0,tim--;
if(sz[dy]==1&&dy<=n)need[dy]=0,tim--;
sz[dy]+=sz[dx];
if(co[dx]&&co[dy]){
now--;
}
co[dy]+=co[dx];
f[dx]=dy;
st[++tot]=dx;
return;
}
void go_pre(int dx){
while(tot>dx){
int x=st[tot];
sz[f[x]]-=sz[x];
if(co[f[x]]-co[x]&&co[x]){
now++;
}
co[f[x]]-=co[x];
if(sz[f[x]]==1&&f[x]<=n)need[f[x]]=1,tim++;
if(sz[x]==1&&x<=n)need[x]=1,tim++;
f[x]=x;
tot--;
}
}
int an[N];
void get(int o,int l,int r){
for(auto k:v[o]){
merge(k.fi,k.se+n);
// cout<<l<<' '<<r<<' '<<k.fi<<' '<<k.se+n<<endl;
}
if(l==r){
if(tim)an[l]=-1;
else an[l]=now;
return;
}
int last=tot;
get(ls,l,mid);
//cout<<"pre->"<<last<<' '<<"now->"<<tot<<endl;
go_pre(last);
get(rs,mid+1,r);
go_pre(last);
}
int main() {
ios::sync_with_stdio(false);
cin>>m>>n>>q;now=n;tim=n;
for(int i=1;i<=n;i++) {
f[i] = i;
need[i]=1;
sz[i]=1;
co[i]=1;
}
for(int i=n+1;i<=n+m;i++){
f[i]=i;
sz[i]=1;
}
for(int i=1;i<=m;i++){
int k;
cin>>k;
for(int j=1;j<=k;j++){
int x;
cin>>x;
g[x].insert({i,1});
}
}
for(int i=1;i<=q;i++){
int x,y;
cin>>x>>y;
auto z=g[x].lower_bound({y,0});
if(z!=g[x].end()){
if((*z).fi==y){
ins(1,1,q+1,(*z).se,i,x,(*z).fi);
// cout<<(*z).fi<<' '<<(*z).se<<endl;
g[x].erase(*z);
}else{
g[x].insert({y,i+1});
}
}else{
g[x].insert({y,i+1});
}
}
for(int i=1;i<=n;i++){
for(auto k:g[i]){
ins(1,1,q+1,k.se,q+1,i,k.fi);
}
}
get(1,1,q+1);
for(int i=2;i<=q+1;i++)cout<<an[i]<<'\n';
return 0;
}