传送门
题解:
每条边的出现是在一定时间范围内的。
于是我们考虑以时间为下标建立线段树,同时维护可回退化并查集就行了。
所谓的可回退化,也可以理解为可以还原到原来的某个版本,我们不使用路径压缩,而是按照 s i z siz siz合并,并且用一个栈来保存所有对并查集的修改操作。
然后需要的时候直接回退到历史版本就行了。
代码:
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<22|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>
inline T get(){
re char c;
while(!isdigit(c=gc()));re T num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
inline int getint(){return get<int>();}
}
using namespace IO;
using std::cerr;
using std::cout;
using pii=std::pair<int,int>;
#define fi first
#define se second
cs int N=5e3+3,M=5e5+5;
int n,m;
int *sta[N<<1],pre[N<<1],top;
inline void pack(int &x){
sta[++top]=&x;
pre[top]=x;
}
int fa[N],siz[N];
inline int getfa(int x){
return x==fa[x]?x:getfa(fa[x]);
}
inline void merge(int u,int v){
u=getfa(u),v=getfa(v);
if(u==v)return ;
if(siz[u]>siz[v])std::swap(u,v);
pack(siz[v]);siz[v]+=siz[u];
pack(fa[u]);fa[u]=v;
}
std::vector<int> E[M<<2];
std::map<pii,int> ma;
int ecnt,u[M],v[M];
bool ins[M],qe[M];
inline void modify(int k,int l,int r,cs int &ql,cs int &qr,cs int &id){
if(ql<=l&&r<=qr)return E[k].push_back(id);
int mid=(l+r)>>1;
if(ql<=mid)modify(k<<1,l,mid,ql,qr,id);
if(mid<qr)modify(k<<1|1,mid+1,r,ql,qr,id);
}
inline void solve(int k,int l,int r){
int low=top;
for(int re e:E[k])merge(u[e],v[e]);
if(l==r){
if(qe[l])puts(getfa(u[l])==getfa(v[l])?"Y":"N");
while(top>low){*sta[top]=pre[top];--top;}
return ;
}
int mid=(l+r)>>1;
solve(k<<1,l,mid);
solve(k<<1|1,mid+1,r);
while(top>low){*sta[top]=pre[top];--top;}
}
signed main(){
// freopen("graph.in","r",stdin);
n=getint(),m=getint();
for(int re i=1;i<=m;++i)switch(getint()){
case 0:{
u[i]=getint(),v[i]=getint();
if(u[i]>v[i])std::swap(u[i],v[i]);
ma[pii(u[i],v[i])]=i;
break;
}
case 1:{
u[i]=getint(),v[i]=getint();
if(u[i]>v[i])std::swap(u[i],v[i]);
int id=ma[pii(u[i],v[i])];
ins[id]=ins[i]=true;
modify(1,1,m,id,i,id);
break;
}
case 2:{
qe[i]=true;
u[i]=getint(),v[i]=getint();
break;
}
}
for(int re i=1;i<=n;++i)fa[i]=i,siz[i]=1;
for(int re i=1;i<=m;++i)if(!ins[i]&&!qe[i])modify(1,1,m,i,m,i);
solve(1,1,m);
return 0;
}