又是一道整体二分的题目,对于每段时间进行操作,判奇环,如果两个点已经联在一起并且是个奇环那么就不是二分图,不同于之前的树状数组,我们要对并查集进行清空操作,因此我们采用按秩合并,将小的合并到大的上面,这样复杂度就变为了O(NlogN)
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=300005; 4 struct edge 5 { 6 int u,v,st,ed; 7 }; 8 struct EDGE 9 { 10 int x,y; 11 }st[N*10]; 12 int n,m,T,fa[N],dis[N],siz[N],top,ans[N]; 13 vector<edge> g; 14 int getfa(int x){return x==fa[x]?x:getfa(fa[x]);} 15 int getdis(int x){return x==fa[x]?0:dis[x]^getdis(fa[x]);} 16 void restore(int b) 17 { 18 while(top>b) 19 { 20 int fx=st[top].x; 21 int fy=st[top].y; 22 top--; 23 siz[fx]-=siz[fy]; 24 fa[fy]=fy; 25 dis[fy]=0; 26 } 27 } 28 void solve(int l,int r,vector<edge> w) 29 { 30 int s=w.size(); 31 int cur=top; 32 int mid=l+r>>1; 33 vector<edge> w1,w2; 34 for(int i=0;i<s;++i) 35 { 36 edge tmp=w[i]; 37 if(tmp.st==l&&tmp.ed==r) 38 { 39 int fx=getfa(tmp.u); 40 int fy=getfa(tmp.v); 41 int z=getdis(tmp.u)^getdis(tmp.v)^1; 42 if(fx==fy) 43 { 44 if(z) 45 { 46 for(int j=l;j<=r;++j) ans[j]=1; 47 restore(cur); 48 return; 49 } 50 } 51 else 52 { 53 if(siz[fx]>siz[fy]) 54 { 55 siz[fx]+=siz[fy]; 56 fa[fy]=fx; 57 dis[fy]=z; 58 st[++top]=(EDGE){fx,fy}; 59 } 60 else 61 { 62 siz[fy]+=siz[fx]; 63 fa[fx]=fy; 64 dis[fx]=z; 65 st[++top]=(EDGE){fy,fx}; 66 } 67 } 68 } 69 else if(tmp.ed<=mid) w1.push_back(tmp); 70 else if(tmp.st>mid) w2.push_back(tmp); 71 else 72 { 73 w1.push_back((edge){tmp.u,tmp.v,tmp.st,mid}); 74 w2.push_back((edge){tmp.u,tmp.v,mid+1,tmp.ed}); 75 } 76 } 77 if(l!=r) 78 { 79 if(w1.size()) solve(l,mid,w1); 80 if(w2.size()) solve(mid+1,r,w2); 81 } 82 restore(cur); 83 } 84 int main() 85 { 86 scanf("%d%d%d",&n,&m,&T); 87 for(int i=1;i<=m;++i) 88 { 89 int u,v,sta,ed; 90 scanf("%d%d%d%d",&u,&v,&sta,&ed); 91 if(sta==ed) continue; 92 sta++; 93 g.push_back((edge){u,v,sta,ed}); 94 } 95 for(int i=1;i<=n;++i) fa[i]=i,siz[i]=1; 96 solve(1,T,g); 97 for(int i=1;i<=T;++i) 98 if(ans[i]) puts("No"); 99 else puts("Yes"); 100 return 0; 101 }