【xsy2506】 bipartite 并查集+线段树
题目大意:有n个点,你需要操作m次。每次操作为加入/删除一条边。
问你每次操作后,这n个点构成的图是否是二分图。
数据范围:n,m≤105。
此题并没有强制在线,考虑离线做法。
一条边在某个时间被加入,然后又被删除。
设这条边出现的时间为[l,r],我们开一棵线段树,在对应的区间上标记出这一条线段。
最后我们遍历整个线段树,把这些线段往并查集上加,同时维护当前点的颜色,然后简单判断下就没了。
这个并查集需要支持撤销操作,所以不能路径压缩,需要按秩合并
时间复杂度:O(nlog2 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\n"); 52 else if(a[x].l==a[x].r) printf("YES\n"); 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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
2018-03-19 【2018北京集训6】Lcm DFT&FWT