题解可以看Manchery博客
分不清左右儿子的我……
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N=50010;
struct VT{
struct NODE{
NODE *ch[2],*f;
ll add,mx,mn,sum,rev,size,w;
void set(int x){
ch[0]=ch[1]=f=0;
add=rev=0; mx=mn=sum=w=x; size=1;
}
void Reverse(){
rev^=1;
}
void Add(ll x){
add+=x; mx+=x; mn+=x; sum+=size*x; w+=x;
}
void Push(){
if(add){
if(ch[0]) ch[0]->Add(add);
if(ch[1]) ch[1]->Add(add);
add=0;
}
if(rev){
swap(ch[0],ch[1]);
if(ch[0]) ch[0]->Reverse();
if(ch[1]) ch[1]->Reverse();
rev=0;
}
}
void Up(){
size=1; mx=mn=sum=w;
if(ch[0])
size+=ch[0]->size,mx=max(mx,ch[0]->mx),mn=min(mn,ch[0]->mn),sum+=ch[0]->sum;
if(ch[1])
size+=ch[1]->size,mx=max(mx,ch[1]->mx),mn=min(mn,ch[1]->mn),sum+=ch[1]->sum;
}
}a[N];
void rot(NODE *x){
NODE *y=x->f,*z=y->f; int wh=y->ch[1]==x;
if(z) z->ch[z->ch[1]==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; y->Up(); x->Up();
}
void PUSHTOP(NODE *x){
if(x->f) PUSHTOP(x->f);
x->Push();
}
void splay(NODE *x){
PUSHTOP(x);
while(x->f){
NODE *y=x->f;
if(y->f && (y->f->ch[1]==y)==(y->ch[1]==x)) rot(y);
rot(x);
}
}
int Size(NODE *x){
if(!x) return 0;
return x->size;
}
NODE *find_kth(NODE *rt,int k){
NODE *x=rt;
if(x->size0;
while(1){
x->Push();
if(Size(x->ch[0])+1==k) return x;
if(Size(x->ch[0])>=k) x=x->ch[0];
else k-=Size(x->ch[0])+1,x=x->ch[1];
}
return x;
}
}T1;
typedef VT::NODE* P;
struct LINKCUTTREE{
struct NODE{
NODE *ch[2],*f; P val;
int rev,size;
void Up(){
size=1;
if(ch[0]) size+=ch[0]->size;
if(ch[1]) size+=ch[1]->size;
}
void Push(){
if(!rev) return ;
swap(ch[0],ch[1]);
if(ch[0]) ch[0]->rev^=1;
if(ch[1]) ch[1]->rev^=1;
rev=0;
}
}a[N];
void set(int x,int y){
a[x].ch[0]=a[x].ch[1]=a[x].f=0;
a[x].rev=0; (a[x].val=T1.a+x)->set(y);
}
int isl(NODE *x){
return !x->f || (x->f->ch[0]!=x && x->f->ch[1]!=x);
}
int isr(NODE *x){
return x->f && x->f->ch[1]==x;
}
void rot(NODE *x){
NODE *y=x->f,*z=y->f; int wh=isr(x);
if(!isl(y)) z->ch[z->ch[1]==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; y->Up(); x->Up();
swap(x->val,y->val);
}
void PUSHTOP(NODE *x){
if(!isl(x)) PUSHTOP(x->f);
x->Push();
}
void splay(NODE *x){
PUSHTOP(x);
for(;!isl(x);rot(x))
if(!isl(x->f)) rot(isr(x->f)^isr(x)?x:x->f);
}
int Size(NODE *x){
return !x?0:x->size;
}
void access(NODE *x){
NODE *lst=0;
while(x){
splay(x);
if(x->ch[1]){
int rk=Size(x->ch[0])+2;
P t=T1.find_kth(x->val,rk);
T1.splay(t);
x->val=t->ch[0]; x->ch[1]->val=t; x->ch[1]=0;
t->ch[0]->f=0; t->ch[0]=0; t->Up();
T1.splay(x->val);
}
if(lst){
P t=T1.find_kth(x->val,x->val->size);
T1.splay(t);
t->ch[1]=lst->val; lst->val->f=t; t->Up();
lst->val=0;
x->ch[1]=lst;
T1.splay(x->val);
}
lst=x; x->Up(); x=x->f;
}
}
void reverse(NODE *x){
access(x); splay(x); x->rev^=1; x->val->Reverse();
}
void link(int x,int y){
reverse(a+x);
reverse(a+y);
a[x].f=a+y;
access(a+x);
}
ll Qmax(int x,int y){
reverse(a+x); access(a+y); splay(a+y); return (a+y)->val->mx;
}
ll Qmin(int x,int y){
reverse(a+x); access(a+y); splay(a+y); return (a+y)->val->mn;
}
ll Qsum(int x,int y){
reverse(a+x); access(a+y); splay(a+y); return (a+y)->val->sum;
}
void Add(int x,int y,int z){
reverse(a+x); access(a+y); splay(a+y); (a+y)->val->Add(z);
}
void Rev(int x,int y){
reverse(a+x); access(a+y); splay(a+y); (a+y)->val->Reverse();
}
}LCT;
int n,m,r;
char opt[10];
int main(){
freopen("1.in","r",stdin);
//freopen("1.out","w",stdout);
scanf("%d%d%d",&n,&m,&r);
for(int i=1;i<=n;i++) LCT.set(i,0);
for(int i=1,x,y;i<=n-1;i++)
scanf("%d%d",&x,&y),LCT.link(x,y);
for(int i=1,x,y,w;i<=m;i++){
scanf("%s %d%d",opt,&x,&y);
if(!strcmp(opt,"Increase"))
scanf("%d",&w),LCT.Add(x,y,w);
else if(!strcmp(opt,"Sum"))
printf("%lld\n",LCT.Qsum(x,y));
else if(!strcmp(opt,"Major"))
printf("%lld\n",LCT.Qmax(x,y));
else if(!strcmp(opt,"Minor"))
printf("%lld\n",LCT.Qmin(x,y));
else LCT.Rev(x,y);
}
return 0;
}