题意:中文
思路:直接并查集维护就行了,对于区间合并的我用一个数组记录和它一个集合的最远点即可
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=200010;
int f[maxn],Rank[maxn],Las[maxn];
int find1(int x){
if(f[x]==x) return x;
else return f[x]=find1(f[x]);
}
void unite(int x,int y){
x=find1(x);y=find1(y);
if(x==y) return ;
if(Rank[x]<Rank[y]) f[x]=y;
else{
f[y]=x;
if(Rank[x]==Rank[y]) Rank[x]++;
}
}
inline int getint(){
int res=0;
char c=getchar();
bool mi=false;
while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
return mi ? -res : res;
}
int main(){
int n,m,u,v,op;
while(scanf("%d%d",&n,&m)!=-1){
for(int i=0;i<=n;i++) f[i]=i,Rank[i]=0,Las[i]=i-1;
while(m--){
op=getint();u=getint();v=getint();
if(op==3){
if(find1(u)==find1(v)) printf("YES\n");
else printf("NO\n");
}else if(op==1) unite(u,v);
else{
int tmp1;
for(int i=v;i>=u;i=tmp1){
tmp1=Las[i];
unite(i,u);
Las[i]=Las[u];
}
}
}
}
return 0;
}