题目
思路
首先,我们可以选择暴力。用t(时间)个并查集维护每一个状态,每次查询随便搞搞即可。
但是很明显会MLE、TLE。
我们可以发现,每次加入一条边,只需更新一个点的father(不用路径压缩),而且,每个点只会更新一个father(用按质合并)。
所以我们可以考虑用一个year数组来记录那个点加入集合的时间,getfather的时候判断当前点是否在当前时间之间加入集合。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=300077;
int v=0,yr=0,f[maxn],year[maxn],z[maxn],n,m;
bool is_mad=0;
char c[2];
int gf(int x,int t)
{
while(x!=f[x]&&year[x]<=t) x=f[x];
return x;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1; i<=n; i++)
{
f[i]=i; z[i]=1;
}
while(m--)
{
scanf("%s",c);
if(c[0]=='K')
{
scanf("%d",&v); is_mad=0;
}else
if(c[0]=='R')
{
int x,y;
scanf("%d%d",&x,&y);
if(is_mad)
{
if((x+=v)>=n) x-=n;
if((y+=v)>=n) y-=n;
}
yr++;
x=gf(x,yr); y=gf(y, yr);
if(x==y) continue;
if(z[x]<z[y])
{
f[x]=y; z[y]+=z[x]; year[x]=yr;
}
else
{
f[y]=x; z[x]+=z[y]; year[y]=yr;
}
}else
if(c[0]=='T')
{
int st,ed,t;
scanf("%d%d%d",&st,&ed,&t);
if(is_mad=((gf(st,yr-t)==gf(ed,yr-t))||(gf(st,yr)^gf(ed,yr)))) printf("N\n");
else printf("Y\n");
}
}
}