神犇有一个n个节点的图。因为神犇是神犇,所以在T时间内一些边会出现后消失。神犇要求出每一时间段内这个图是否是二分图。这么简单的问题神犇当然会做了,于是他想考考你。
标签:最大 个数 bzoj start esc rewrite closed 可持久化并查集 相加
#include <iostream> #include <cstdio> #include <cstdlib> #include <algorithm> #include <vector> #include <cstring> #include <queue> #include <complex> #include <stack> #define LL long long int #define dob double #define FILE "" using namespace std; const int N = 100010; struct edge{int x,y,st,ed;}; struct U_F_set{ int fa[N],dis[N],size[N],stack1[N],stack2[N],stack3[N],top; inline int find(register int x){ while(fa[x]!=x)x=fa[x]; return x; } inline int getdis(register int x,register int ans=0){ while(x!=fa[x]) ans^=dis[x],x=fa[x]; return ans; } inline void merge(register int x,register int y,register int val){ if(size[x]>size[y]){ top++;stack1[top]=y;stack2[top]=x;stack3[top]=size[x]; fa[y]=x;dis[y]=val;size[x]+=size[y]; } else{ top++;stack1[top]=x;stack2[top]=y;stack3[top]=size[y]; fa[x]=y;dis[x]=val;size[y]+=size[x]; } } inline void rewrite(){ size[stack2[top]]=stack3[top];fa[stack1[top]]=stack1[top]; dis[stack1[top]]=0;top--; } }UF; int n,m,T,Ans[N]; inline int gi(){ int x=0,res=1;char ch=getchar(); while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)res*=-1;ch=getchar();} while(ch<=‘9‘&&ch>=‘0‘)x=x*10+ch-48,ch=getchar(); return x*res; } inline void solve(int l,int r,vector<edge>Edge){ int mid=(l+r)>>1,now=UF.top; vector<edge>El,Er; for(int i=0,I=Edge.size();i<I;++i){ edge e=Edge[i]; if(e.st==l && e.ed==r){ int x=e.x,y=e.y; int f1=UF.find(x),f2=UF.find(y); int dis=UF.getdis(x)^UF.getdis(y)^1; if(f1!=f2)UF.merge(f1,f2,dis); else if(dis&1){ for(int i=l;i<=r;++i)Ans[i]=1; while(now!=UF.top)UF.rewrite(); return; } } else if(e.ed<=mid)El.push_back(e); else if(e.st>mid)Er.push_back(e); else{ edge el=e,er=e;el.ed=mid;er.st=mid+1; El.push_back(el);Er.push_back(er); } } if(l==r)Ans[l]=0;else solve(l,mid,El),solve(mid+1,r,Er); while(now!=UF.top)UF.rewrite(); } int main() { n=gi();m=gi();T=gi(); vector<edge>Edge; for(int i=1;i<=n;++i)UF.fa[i]=i,UF.size[i]=1; for(int i=1;i<=m;++i){ int u=gi(),v=gi(),st=gi()+1,ed=gi(); if(st>ed)continue; Edge.push_back((edge){u,v,st,ed}); } solve(1,T,Edge); for(int i=1;i<=T;++i) printf("%s\n",Ans[i]?"No":"Yes"); return 0; }
标签:最大 个数 bzoj start esc rewrite closed 可持久化并查集 相加
原文地址:http://www.cnblogs.com/fenghaoran/p/7608175.html