题目链接:CodeForces 566D Restructuring Company
思路:
操作1:直接合并。
操作2:由于是一个区间段,区间所在集合编号确定。下次这个区间再有合并操作了,直接拿区间编号合并。所以用个数组记录,当前集合下一个集合的编号。
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
const int MOD = 10000007;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const int maxn = 200050;
int father[maxn];
int a[maxn]; //a[i]指向下一个与i不在同一集合里的元素
int find(int x)
{
if(father[x]!=x)
father[x] = find(father[x]);
return father[x];
}
void Union(int x,int y)
{
x = find(x);
y = find(y);
if(x!=y)
father[y] = x;
}
bool judge(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)
return true;
else
return false;
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
father[i] = i;
a[i] = i+1;
}
for(int i=0;i<q;i++)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==1)
{
Union(x,y);
}
else if(op==2)
{
int tmp;
for(int i=x+1;i<=y;i=tmp)
{
Union(i-1,i);
tmp = a[i];
a[i] = y+1; //该段区间所有元素的下一个元素都是y+1
}
}
else
{
if(judge(x,y))
printf("YES\n");
else
printf("NO\n");
}
}
return 0;
}