给你一个有 n 个顶点的无向图,初始时没有边,有 q 个操作,每个操作加入或删除一条边,要求每次操作后输出这个图是否是二分图。
显然一个图是二分图的充要条件是不存在长度为奇数的环。
对于图中可能出现的每条边,记录它出现的某些区间,然后考虑分治。
Solve(l,r,U) 表示处理 [l,r] 的答案,其中 U 表示出现区间在 [l,r] 内的边的集合。
用 LCT 维护图的连通,对于出现区间刚好等于 [l,r] 的边 (x,y) ,判断图中 x 与 y 是否连通。如果连通,再求出 x 到 y 的路径长度,如果是偶数,那么加入边 (x,y) 后会出现长度为奇数的环, [l,r] 的答案全是 NO 。如果不连通,将 x 与 y 连上并分治求 [l,mid],[mid+1,r] 。回溯时删除。
#include
#include
#include
#include
#include
#include
using namespace std;
#define N 100010
struct Node{
Node(int x=0,int y=0):x(x),y(y){}
int x,y;
}a[N],q[N];
struct P{
P(int w=0,int x=0,int y=0):w(w),x(x),y(y){}
int w,x,y;
}t;
int x,y,i,j,k,n,m,f[N],ch[N][2],s[N],l[N],Q,p[N];
bool b[N],r[N],v[N];
inline bool Get(int x){
return ch[f[x]][1]==x;
}
inline void Up(int x){
s[x]=s[ch[x][0]]+s[ch[x][1]]+1;
}
inline void Update_rev(int x){
r[x]^=1;
swap(ch[x][0],ch[x][1]);
}
inline void Down(int x){
if(r[x]){
Update_rev(ch[x][0]);
Update_rev(ch[x][1]);
r[x]=0;
}
}
inline void Rotate(int x){
bool d=Get(x);int y=f[x];
if(b[y])b[x]=1,b[y]=0;else ch[f[y]][Get(y)]=x;
ch[y][d]=ch[x][d^1];f[ch[y][d]]=y;
ch[x][d^1]=y;f[x]=f[y];f[y]=x;Up(y);
}
inline void Push(int x){
if(!b[x])Push(f[x]);
Down(x);
}
inline void Splay(int x){
for(Push(x);!b[x];Rotate(x))
if(!b[f[x]])Rotate(Get(x)==Get(f[x])?f[x]:x);
Up(x);
}
inline void Access(int x){
int y=0;
while(x){
Splay(x);
b[ch[x][1]]=1;ch[x][1]=y;b[y]=0;Up(x);
y=x;x=f[x];
}
}
inline void mr(int x){
Access(x);Splay(x);Update_rev(x);
}
inline void Link(int x,int y){
mr(x);f[x]=y;
}
inline void Del(int x,int y){
mr(x);Access(y);Splay(y);
ch[y][0]=f[x]=0;b[x]=1;Up(y);
}
inline int Find(int x){
if(f[x])return Find(f[x]);
return x;
}
inline int Query(int x,int y){
mr(x);Access(y);Splay(y);
return s[y];
}
map<int,int>M[N];
vectorg;
inline void Solve(int l,int r,vector&g){
vectorL,R;
vector<int>c;
int Mid=l+r>>1;
for(int i=0;iif(g[i].x==l&&g[i].y==r){
if(Find(a[g[i].w].x)!=Find(a[g[i].w].y))Link(a[g[i].w].x,a[g[i].w].y),c.push_back(i);else
if(Query(a[g[i].w].x,a[g[i].w].y)&1){
for(int j=l;j<=r;j++)puts("NO");
for(int j=0;jreturn;
}
}else if(g[i].y<=Mid)L.push_back(g[i]);else
if(g[i].x>Mid)R.push_back(g[i]);else L.push_back(P(g[i].w,g[i].x,Mid)),R.push_back(P(g[i].w,Mid+1,g[i].y));
}
if(l==r){
puts("YES");
for(int j=0;jreturn;
}
Solve(l,Mid,L);Solve(Mid+1,r,R);
for(int j=0;jint main(){
scanf("%d%d",&n,&Q);
for(i=1;i<=n;i++)b[i]=s[i]=1;
for(i=1;i<=Q;i++){
scanf("%d%d",&q[i].x,&q[i].y);
if(q[i].x>q[i].y)swap(q[i].x,q[i].y);
if(!M[q[i].x][q[i].y])M[q[i].x][q[i].y]=++m,a[m]=Node(q[i].x,q[i].y);
}
for(i=1;i<=Q;i++){
x=M[q[i].x][q[i].y];
if(p[x])g.push_back(P(x,p[x],i-1)),p[x]=0;else p[x]=i;
}
for(i=1;i<=m;i++)if(p[i])g.push_back(P(i,p[i],Q));
Solve(1,Q,g);
return 0;
}