之前询问得到的树用LCT维护,然后每次询问从根开始询问
询问次数和复杂度都是 O(nlogn)O(nlogn) 的
UPD:被HACK了
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include "rts.h"
using namespace std;
const int N=300010;
struct node{
node *ch[2],*f;
int rev;
}a[N],*root;
inline int isl(node *x){ return !x->f || (x->f->ch[0]!=x && x->f->ch[1]!=x); }
inline int isr(node *x){ return x->f && x->f->ch[1]==x; }
inline void Push(node *x){
if(!x || !x->rev) return ;
swap(x->ch[0],x->ch[1]);
if(x->ch[0])
x->ch[0]->rev^=1;
if(x->ch[1])
x->ch[1]->rev^=1;
x->rev=0;
}
void Pushtop(node *x){
if(!isl(x)) Pushtop(x->f); Push(x);
}
inline void rot(node *x){
node *y=x->f,*z=y->f; int wh=isr(x);
if(!isl(y)) z->ch[isr(y)]=x; x->f=z;
if(y->ch[wh]=x->ch[wh^1]) y->ch[wh]->f=y;
(x->ch[wh^1]=y)->f=x;
}
inline void splay(node *x){
Pushtop(x);
for(;!isl(x);rot(x)) if(!isl(x->f)) rot(isr(x->f)^isr(x)?x:x->f);
}
inline void access(node *x){
for(node *t=0;x;x=x->f)
splay(x),x->ch[1]=t,t=x;
}
inline void reverse(node *x){
access(x); splay(x); x->rev^=1;
}
inline void link(int _x,int _y){
node *x=a+_x,*y=a+_y;
x->f=y; //access(x);
}
int id[N],vis[N],dpt[N];
inline bool isfa(node *x,node *y){
if(y==x) return true;
while(!isl(y)){
y=y->f;
if(y==x) return true;
}
return false;
}
inline node *Root(node *x){
while(!isl(x)) x=x->f;
return x;
}
inline void work(int n){
vis[1]=1; srand(19260817);
for(int i=1;i<=n;i++) id[i]=i;
random_shuffle(id+1,id+1+n);
int p1=1,p2=1;
for(int i=1;i<=n;i++){
int x=id[i];
if(vis[x]) continue;
if(rand()&1) swap(p1,p2);
int c=explore(p1,x);
if(vis[c]) swap(p1,p2),c=explore(p1,x);
vis[c]=1; p1=c;
while(!vis[x]){
c=explore(p1,x); vis[p1=c]=1;
}
}
}
void play(int n,int T,int dataType) {
if(dataType==3)
return work(n);
root=a+1; vis[1]=1;
for(int i=1;i<=n;i++) id[i]=i;
random_shuffle(id+1,id+1+n);
for(int i=1;i<=n;i++){
int x=id[i];
if(vis[x]) continue;
reverse(root);
node *cur=root;
while(1){
Push(cur);
int c=explore(cur-a,x);
if(!vis[c]){
vis[c]=1; dpt[c]=dpt[cur-a]+1; link(c,cur-a); cur=a+c;
if(c==x) break;
continue;
}
if(isfa(cur,a+c))
cur=dpt[c]>dpt[cur-a]?cur->ch[1]:cur->ch[0];
else
cur=Root(a+c);
}
access(cur);
}
}