题目大意:有$n$个点,你需要操作$m$次。每次操作为加入/删除一条边。
问你每次操作后,这$n$个点构成的图是否是二分图。
数据范围:$n,m≤10^5$。
此题并没有强制在线,考虑离线做法。
一条边在某个时间被加入,然后又被删除。
设这条边出现的时间为$[l,r]$,我们开一棵线段树,在对应的区间上标记出这一条线段。
最后我们遍历整个线段树,把这些线段往并查集上加,同时维护当前点的颜色,然后简单判断下就没了。
这个并查集需要支持撤销操作,所以不能路径压缩,需要按秩合并
时间复杂度:$O(nlog^2 n)$。
1 #include<bits/stdc++.h> 2 #define M 100005 3 #define mid ((a[x].l+a[x].r)>>1) 4 using namespace std; 5 6 int f[M]={0},siz[M]={0},val[M]={0}; int get(int x){return x==f[x]?x:get(f[x]);} 7 int getdis(int x){return x==f[x]?0:val[x]+getdis(f[x]);} 8 int n,m,ok=1; 9 map<int,int> mp[M]; 10 11 struct seg{ 12 int l,r; vector<int> u,v,F; 13 void add(){ 14 int S=u.size(); 15 for(int i=0;i<S;i++){ 16 int U=get(u[i]),V=get(v[i]); 17 if(U==V){ 18 if((getdis(u[i])+getdis(v[i]))%2==0) ok=0; 19 F.push_back(-1); continue; 20 } 21 if(siz[U]<siz[V]){swap(U,V); swap(u[i],v[i]);} 22 int d=getdis(u[i])+getdis(v[i]); 23 F.push_back(V); f[V]=U; val[V]=(d+1)&1; siz[U]+=siz[V]; 24 } 25 } 26 void del(){ 27 int S=u.size(); 28 for(int i=S-1;~i;i--){ 29 if(F[i]==-1) continue; 30 int U=get(u[i]),V=F[i]; 31 siz[U]-=siz[V]; 32 f[V]=V; val[V]=0; 33 } 34 } 35 36 }a[M<<2]={0}; 37 38 void build(int x,int l,int r){ 39 a[x].l=l; a[x].r=r; if(l==r) return; 40 build(x<<1,l,mid); build(x<<1|1,mid+1,r); 41 } 42 void updata(int x,int l,int r,int U,int V){ 43 if(l<=a[x].l&&a[x].r<=r){a[x].u.push_back(U); a[x].v.push_back(V);return;} 44 if(l<=mid) updata(x<<1,l,r,U,V); 45 if(mid<r) updata(x<<1|1,l,r,U,V); 46 } 47 48 int solve(int x){ 49 int lastok=ok; 50 a[x].add(); 51 if(ok==0) for(int i=a[x].l;i<=a[x].r;i++) printf("NO "); 52 else if(a[x].l==a[x].r) printf("YES "); 53 else solve(x<<1),solve(x<<1|1); 54 a[x].del(); 55 ok=lastok; 56 } 57 58 int main(){ 59 scanf("%d%d",&n,&m); 60 build(1,1,m); 61 for(int i=1;i<=n;i++) f[i]=i,siz[i]=1; 62 for(int i=1;i<=m;i++){ 63 int u,v; scanf("%d%d",&u,&v); 64 if(u<v) swap(u,v); 65 if(mp[u][v]){ 66 updata(1,mp[u][v],i-1,u,v); 67 mp[u][v]=0; 68 }else mp[u][v]=i; 69 } 70 for(int i=1;i<=n;i++){ 71 for(map<int,int>::iterator it=mp[i].begin();it!=mp[i].end();it++) 72 if(it->second) 73 updata(1,it->second,m,i,it->first); 74 } 75 solve(1); 76 }