分析:
比较简单的LCT维护子树板子题(set都用不着…)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 100010
using namespace std;
typedef long long ll;
struct node *NIL;
struct node{
node *ch[2],*fa;
int sum,rev,val;
bool Isroot(){
return fa==NIL||(fa->ch[1]!=this&&fa->ch[0]!=this);
}
bool Dir(){
return fa->ch[1]==this;
}
void Setchild(node *x,int d){
ch[d]=x;
if(x!=NIL)
x->fa=this;
}
void pushup(){
sum=ch[0]->sum+ch[1]->sum+val;
}
void pushdown(){
if(rev){
swap(ch[0],ch[1]);
if(ch[0]!=NIL)
ch[0]->rev^=1;
if(ch[1]!=NIL)
ch[1]->rev^=1;
rev=0;
}
}
}Tree[MAXN];
void Rotate(node *x){
node *y=x->fa;
y->pushdown(),x->pushdown();
int d=x->Dir();
if(y->Isroot())
x->fa=y->fa;
else
y->fa->Setchild(x,y->Dir());
y->Setchild(x->ch[!d],d);
x->Setchild(y,!d);
y->pushup();
}
void Splay(node *x){
x->pushdown();
while(x->Isroot()==0){
node *y=x->fa;
if(y->Isroot())
Rotate(x);
else{
if(x->Dir()==y->Dir())
Rotate(y);
else
Rotate(x);
Rotate(x);
}
}
x->pushup();
}
void Access(node *x){
node *c=NIL;
while(x!=NIL){
Splay(x);
x->val-=c->sum;
x->val+=x->ch[1]->sum;
x->Setchild(c,1);
x->pushup();
c=x;
x=x->fa;
}
}
void MakeRoot(node *x){
Access(x);
Splay(x);
x->rev^=1;
}
void Link(node *x,node *y){
MakeRoot(x);
Access(y);
Splay(y);
x->fa=y;
y->val+=x->sum;
y->sum+=x->sum;
}
ll Query(node *x,node *y){
MakeRoot(x);
Access(y);
Splay(y);
ll A=y->ch[1]->sum+y->val;
ll B=x->sum;
return A*B;
}
void init(){
NIL=Tree;
NIL->ch[0]=NIL->ch[1]=NIL->fa=NIL;
}
void Newnode(node *x,int val){
x->sum=x->val=val;
x->ch[0]=x->ch[1]=x->fa=NIL;
}
char s[10];
int main(){
init();
int n,m,u,v;
SF("%d%d",&n,&m);
for(int i=1;i<=n;i++)
Newnode(Tree+i,1);
for(int i=1;i<=m;i++){
SF("%s",s);
SF("%d%d",&u,&v);
if(s[0]=='A')
Link(Tree+u,Tree+v);
else
PF("%lld\n",Query(Tree+u,Tree+v));
// for(int i=1;i<=n;i++)
// PF("%d %d %d %d,%d\n",Tree[i].val,Tree[i].sum,Tree[i].fa-Tree,Tree[i].ch[0]-Tree,Tree[i].ch[1]-Tree);
// PF("------------\n");
}
}