不是题解,违规紫衫。
查询 O(logn),合并 O(n),可过。
#include<cmath>
#include<cstdio>
#include<random>
std::mt19937 chaos(20071109);
struct FHQ{
int siz,rnk,id,pos,tag;
FHQ *lc,*rc;
static FHQ *null;
FHQ(){
siz=rnk=id=pos=tag=0;
lc=rc=this;
}
FHQ(int i,int p){
siz=1,rnk=chaos();
id=i,pos=p;
tag=0;
lc=rc=null;
}
}*FHQ::null=new FHQ();
bool is_null(FHQ* now){
return now==FHQ::null;
}
void update(FHQ* now){
now->siz=now->lc->siz+now->rc->siz+1;
}
void make_tag(FHQ* now,int val){
if(!is_null(now)){
now->tag+=val;
now->pos+=val;
}
}
void spread(FHQ* now){
make_tag(now->lc,now->tag);
make_tag(now->rc,now->tag);
now->tag=0;
}
void split(FHQ* now,FHQ*& L,FHQ*& R,int id){
if(is_null(now))L=R=FHQ::null;
else if(now->id<id){
spread(L=now);
split(L->rc,L->rc,R,id);
update(L);
}else{
spread(R=now);
split(R->lc,L,R->lc,id);
update(R);
}
}
FHQ* merge(FHQ* L,FHQ* R){
if(is_null(L))return R;
if(is_null(R))return L;
if(L->rnk<R->rnk){
spread(L);
L->rc=merge(L->rc,R);
update(L);
return L;
}else{
spread(R);
R->lc=merge(L,R->lc);
update(R);
return R;
}
}
int index(FHQ* now,int id){
if(id==now->id)return now->pos;
spread(now);
if(id<now->id)return index(now->lc,id);
return index(now->rc,id);
}
void insert(FHQ*& now,int id,int pos){
FHQ *L,*R;
split(now,L,R,id);
now=merge(L,merge(new FHQ(id,pos),R));
}
void Merge(FHQ*& L,FHQ*& R){
if(!is_null(L)){
spread(L);
insert(R,L->id,L->pos);
Merge(L->lc,R);
Merge(L->rc,R);
delete L;
L=FHQ::null;
}
}
#define _N_ 30005
int fa[_N_];
FHQ* tree[_N_];
int get_father(int x){
return fa[x]==x?x:fa[x]=get_father(fa[x]);
}
int main(){
for(int i=1;i<=30000;i++){
fa[i]=i;
tree[i]=new FHQ(i,1);
}
int m;
scanf("%d",&m);
while(m--){
static char op[5];
int x,y;
scanf("%s%d%d",op,&x,&y);
int fx=get_father(x);
int fy=get_father(y);
if(*op=='M'){
make_tag(tree[fx],tree[fy]->siz);
if(tree[fx]->siz<tree[fy]->siz){
fa[fx]=fy;
Merge(tree[fx],tree[fy]);
}else{
fa[fy]=fx;
Merge(tree[fy],tree[fx]);
}
}else
if(fx!=fy)printf("-1\n");
else printf("%d\n",std::abs(index(tree[fx],x)-index(tree[fx],y))-1);
}
return 0;
}
(本来想骗分的,结果就过力)
不是题解,违规紫衫。