题意:不断删边加边,问此时的图可不可以为二分图。
解:判断二分图就看有没与奇数环 (没有就可以,有就不行)
时间分治线段树--->来看当前的图有没有奇环(带权并查集)
写一下并查集那里连边:
merge发生在 x,y的祖先身上,我们是在间接连边,最后查询dis一定是正确的
c[i]表示 点i到 它的root的距离。
所以x,y连边之后merge里yy成为新的root:c[xx]表示xx到yy的距离
len=dis[x]^dis[y]^1
c[xx]==len
void Merge(int x,int y,int len){
x=find(x),y=find(y);
if(x==y)return ;
if(rnk[x]>rnk[y])swap(x,y);
else if(rnk[x]==rnk[y])++rnk[y],sta[++sp]=-y;
f[x]=y,c[x]=len,sta[++sp]=x;
}
#include<bits/stdc++.h>
#define en '\n'
typedef long long ll;
const ll maxn= 1e5+3;
const int maxm=maxn<<2;
#define pb push_back
using namespace std;
int rd(){int tem;scanf("%d",&tem);return tem;}
map< pair<int,int>,int>ma;
vector<pair<int,int> >tr[maxm];
void update(int x,int l,int r,int ql,int qr,pair<int,int> val){
if(l>=ql and r<=qr ){tr[x].pb({val});return ; }
int mid=(l+r)>>1;
if(ql<=mid)update(x<<1,l,mid,ql,qr,val);
if(qr>mid)update(x<<1|1,mid+1,r,ql,qr,val);
}
int f[maxn],c[maxn],rnk[maxn],sta[maxn],sp;
int find(int x){for(;x!=f[x];x=f[x]);return x;}
int dis(int x){
int res=0;for(;f[x] and x!=f[x];x=f[x])res^=c[x];return res;
}
void Merge(int x,int y,int len){
x=find(x),y=find(y);
if(x==y)return ;
if(rnk[x]>rnk[y])swap(x,y);
else if(rnk[x]==rnk[y])++rnk[y],sta[++sp]=-y;
f[x]=y,c[x]=len,sta[++sp]=x;
}
void restore(int x){
for(;sp>x;--sp){
if(sta[sp]<0)--rnk[sta[sp]];
else f[sta[sp]]=sta[sp],c[sta[sp]]=0;
}
}
void ask(int x,int l,int r){
int now=sp;
for(int i=0;i<tr[x].size();i++){
int temx=tr[x][i].first,temy=tr[x][i].second;
int xx=find(temx),yy=find(temy);
int len=dis(temx)^dis(temy)^1;
if(xx==yy){
if(len&1){
for(int i=l;i<=r;i++){
puts("NO");
}
restore(now);
return ;
}
}else Merge(temx,temy,len);
}
if(l==r){cout<<"YES"<<en;restore(now);return ;}
int mid=(l+r)>>1;
ask(x<<1,l,mid),ask(x<<1|1,mid+1,r),restore(now);
}
signed main()
{
#ifdef local
freopen("input2.txt","r",stdin);
#endif // local
int n,q;
n=rd(),q=rd();
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=q;i++){
int x=rd(),y=rd();
if(ma[{x,y}]){
update(1,1,q,ma[{x,y}],i-1,{x,y});
ma.erase({x,y});
}
else ma[{x,y}]=i;
}
for(auto x:ma){
update(1,1,q,x.second,q,{x.first.first,x.first.second});
}
ask(1,1,q);
return 0;
}
|