题目大意
一个
n
个点的图,一开始没有边。有
保证任何时候图不存在环。强制在线。
题目分析
并查集维护直径,LCT维护两点距离即可。
时间复杂度
O(qlogn)
。
代码实现
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cctype>
#include <stack>
using namespace std;
int read()
{
int x=0,f=1;
char ch=getchar();
while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();
while (isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x*f;
}
int buf[30];
void write(int x)
{
if (x<0) putchar('-'),x=-x;
for (;x;x/=10) buf[++buf[0]]=x%10;
if (!buf[0]) buf[++buf[0]]=0;
for (;buf[0];putchar(buf[buf[0]--]+'0'));
}
const int N=300005;
struct link_cut_tree
{
int fa[N],size[N],par[N];
int son[N][2];
stack<int> st;
bool mark[N];
bool side(int x){return son[fa[x]][1]==x;}
void R(int x){swap(son[x][0],son[x][1]),mark[x]^=1;}
void update(int x){size[x]=size[son[x][0]]+size[son[x][1]]+1;}
void clear(int x)
{
if (mark[x])
{
if (son[x][0]) R(son[x][0]);
if (son[x][1]) R(son[x][1]);
mark[x]=0;
}
}
void pushdown(int x,int y)
{
for (;x!=y;st.push(x),x=fa[x]);
for (;!st.empty();clear(st.top()),st.pop());
}
void rotate(int x)
{
int y=fa[x];bool s=side(x);
if (fa[y]) son[fa[y]][side(y)]=x;
if (son[x][s^1]) fa[son[x][s^1]]=y;
son[y][s]=son[x][s^1],son[x][s^1]=y;
fa[x]=fa[y],fa[y]=x;
if (par[y]) par[x]=par[y],par[y]=0;
update(y),update(x);
}
void splay(int x,int y)
{
for (pushdown(x,y);fa[x]!=y;rotate(x))
if (fa[fa[x]]!=y)
if (side(x)==side(fa[x])) rotate(fa[x]);
else rotate(x);
}
int access(int x)
{
int nxt=0;
for (;x;update(nxt=x),x=par[x])
{
splay(x,0);
if (son[x][1]) par[son[x][1]]=x,fa[son[x][1]]=0;
if (nxt) par[nxt]=0,fa[nxt]=x;
son[x][1]=nxt;
}
return nxt;
}
void makeroot(int x){R(access(x));}
void link(int x,int y)
{
makeroot(x),access(x),splay(x,0);
par[x]=y,access(x);
}
void cut(int x,int y)
{
makeroot(x),access(y),splay(y,0);
fa[x]=son[y][0]=0,update(y);
}
int dist(int x,int y)
{
makeroot(x),access(y),splay(y,0);
return size[y]-1;
}
}lct;
struct diameter
{
int x[2];
diameter (int x_=0,int y_=0){x[0]=x_,x[1]=y_;}
}d[N];
diameter operator+(diameter u,diameter v)
{
diameter nw=u;
int d0=lct.dist(u.x[0],u.x[1]),tmp=lct.dist(v.x[0],v.x[1]);
if (d0<tmp) d0=tmp,nw=v;
for (int i=0;i<2;++i)
for (int j=0;j<2;++j)
{
tmp=lct.dist(u.x[i],v.x[j]);
if (d0<tmp) d0=tmp,nw=diameter(u.x[i],v.x[j]);
}
return nw;
}
int fa[N],rank[N];
int n,q;
bool online;
int getfather(int son){return fa[son]==son?son:fa[son]=getfather(fa[son]);}
void merge(int x,int y)
{
if (rank[x]>rank[y]) swap(x,y);
fa[x]=y,rank[y]+=rank[x]==rank[y],d[y]=d[x]+d[y];
}
int ask(int x)
{
int y=getfather(x),ret=0;
for (int i=0;i<2;++i) ret=max(ret,lct.dist(x,d[y].x[i]));
return ret;
}
int main()
{
freopen("hike.in","r",stdin),freopen("hike.out","w",stdout);
bool online=read();
n=read(),q=read();
for (int i=1;i<=n;++i) fa[i]=i,d[i]=diameter(i,i),lct.size[i]=1;
for (int lst=0,opt,u,v;q--;)
{
opt=read(),u=read()^(online*lst);
if (opt==1)
{
v=read()^(online*lst);
lct.link(u,v),merge(getfather(u),getfather(v));
}else write(lst=ask(u)),putchar('\n');
}
fclose(stdin),fclose(stdout);
return 0;
}