Even the most successful company can go through a crisis period when you have to make a hard decision — to restructure, discard and merge departments, fire employees and do other unpleasant stuff. Let's consider the following model of a company.
There are n people working for the Large Software Company. Each person belongs to some department. Initially, each person works on his own project in his own department (thus, each company initially consists of n departments, one person in each).
However, harsh times have come to the company and the management had to hire a crisis manager who would rebuild the working process in order to boost efficiency. Let's use team(person) to represent a team where person person works. A crisis manager can make decisions of two types:
- Merge departments team(x) and team(y) into one large department containing all the employees of team(x) and team(y), where x and y (1 ≤ x, y ≤ n) — are numbers of two of some company employees. If team(x) matches team(y), then nothing happens.
- Merge departments team(x), team(x + 1), ..., team(y), where x and y (1 ≤ x ≤ y ≤ n) — the numbers of some two employees of the company.
At that the crisis manager can sometimes wonder whether employees x and y (1 ≤ x, y ≤ n) work at the same department.
Help the crisis manager and answer all of his queries.
Input
The first line of the input contains two integers n and q (1 ≤ n ≤ 200 000, 1 ≤ q ≤ 500 000) — the number of the employees of the company and the number of queries the crisis manager has.
Next q lines contain the queries of the crisis manager. Each query looks like type x y, where
. If type = 1 or type = 2, then the query represents the decision of a crisis manager about merging departments of the first and second types respectively. If type = 3, then your task is to determine whether employees x and y work at the same department. Note that x can be equal to y in the query of any type.
Output
For each question of type 3 print "YES" or "NO" (without the quotes), depending on whether the corresponding people work in the same department.
Examples
Input
8 6 3 2 5 1 2 5 3 2 5 2 4 7 2 1 2 3 1 7
Output
NO YES YES
题目分析:并查集区间合并问题。
关于并查集区间合并,暴力的话一般就超时。区间合并可以看作是点合并的扩展,比如说点合并时,如果两个点属于同一个集合,那我们可以不看这个点了,直接跳过看下一个点就行了。区间合并也是这个道理,如果这个区间跟要合并的区间已经是同一个集合了,那我们直接跳过这个区间看下一个区间就行了,所以在for循环中步长表达式是区间长度。
实行方法是多定义一个nex数组,nex[i]代表 i 所在区间的下一个区间(当然这两个区间不属于同一个集合)。
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <cstdio>
#include <stack>
#include <set>
#define MAXN 200004
using namespace std;
int f[MAXN];
int nex[MAXN];
int getf(int a){
int x = a;
while(f[x] != x){
x = f[x];
}
while(f[a] != x){
int j = a;
a = f[a];
f[j] = x;
}
return x;
}
void Union(int a,int b){
int fa = getf(a);
int fb = getf(b);
if(fa != fb) f[fb] = fa;
}
int main(){
int n,q;
while(~scanf("%d%d",&n,&q)){
for(int i=1;i<=n;++i){
f[i] = i;
nex[i] = i+1; //初始化nex数组,此时每个值各自组成一个区间,它的不属于同一个集合的下一个区间就是 i+1
}
int op;
int a,b;
for(int i=0;i<q;++i){
scanf("%d%d%d",&op,&a,&b);
if(op == 1){
Union(a,b);
}
else if(op == 2){
int tmp;
for(int i=a;i<=b;i=tmp){
Union(a,i);
tmp = nex[i]; //步长,直接跳过同属于一个集合的区间的长度
nex[i] = nex[b]; //合并后i的下一个区间跟b是相等的
}
}
else{
if(getf(a) == getf(b)) cout << "YES" << endl;
else cout << "NO" << endl;
}
}
}
return 0;
}