直接上题解吧 有空去看看那篇集训队论文
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#define dprintf(...) fprintf(stderr,__VA_ARGS__)
using namespace std;
typedef long long ll;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }
return *p1++;
}
inline void read(int &x){
char c=nc(),b=1;
for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;
for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}
inline void read(char *s){
char c=nc();int len=0;
for (;!(c>='A' && c<='Z') && !(c>='a' && c<='z');c=nc());
for (;(c>='A' && c<='Z')||(c>='a' && c<='z');s[++len]=c,c=nc()); s[++len]=0;
}
const int N=50005;
struct T1{
struct node{
node *ch[2],*p; int size;
ll f,v,Sum,Max,Min;
int rev;
bool dir() { return p->ch[1]==this; }
void setc(node *x,int d) { ch[d]=x; x->p=this; }
void reverse(){
rev^=1; swap(ch[0],ch[1]);
}
void update(){
size=ch[0]->size+ch[1]->size+1;
Sum=ch[0]->Sum+ch[1]->Sum+v;
Max=max(max(ch[0]->Max,ch[1]->Max),v);
Min=min(min(ch[0]->Min,ch[1]->Min),v);
}
void mark(int w){
v+=w; f+=w; Max+=w; Min+=w; Sum+=(ll)size*w;
}
void pushdown(node *null){
if (rev){
if (ch[0]!=null) ch[0]->reverse();
if (ch[1]!=null) ch[1]->reverse();
rev=0;
}
if (f){
if (ch[0]!=null) ch[0]->mark(f);
if (ch[1]!=null) ch[1]->mark(f);
f=0;
}
}
}*null,Mem[N];
T1() { null=Mem; null->p=null->ch[0]=null->ch[1]=null; null->size=null->Sum=0; null->Max=-1LL<<60; null->Min=1LL<<60; }
void rot(node *x){
if (x==null || x->p==null) return;
bool d=x->dir(); node *p=x->p;
if (p->p!=null) p->p->setc(x,p->dir()); else x->p=null;
p->setc(x->ch[d^1],d); x->setc(p,d^1); p->update(); x->update();
}
node *sta[N];
void splay(node *x){
node *y=x; int pnt=0;
while (y!=null) sta[++pnt]=y,y=y->p;
for (int i=pnt;i;i--) sta[i]->pushdown(null);
while (x->p!=null)
if (x->p->p==null)
rot(x);
else
x->dir()==x->p->dir()?(rot(x->p),rot(x)):(rot(x),rot(x));
}
node *findkth(node *rt,int k){
if (rt->size<k) return null;
node *x=rt;
while (k){
x->pushdown(null);
if (x->ch[0]->size+1==k)
break;
else
x->ch[0]->size+1<k?(k-=x->ch[0]->size+1,x=x->ch[1]):x=x->ch[0];
}
splay(x); return x;
}
}Val;
typedef T1::node *pt;
struct T2{
struct node{
node *ch[2],*p,*fat; pt val;
int rev; int size,idx;
bool dir() { return p->ch[1]==this; }
void setc(node *x,int d) { ch[d]=x; x->p=this; }
void reverse(){
rev^=1; swap(ch[0],ch[1]);
}
void update(){
size=ch[0]->size+ch[1]->size+1;
}
void pushdown(node *null){
if (rev){
if (ch[0]!=null) ch[0]->reverse();
if (ch[1]!=null) ch[1]->reverse();
rev=0;
}
}
}*null,Mem[N];
T2() { null=Mem; null->p=null->ch[0]=null->ch[1]=null->fat=null; null->size=0; }
void rot(node *x){
if (x==null || x->p==null) return;
bool d=x->dir(); node *p=x->p;
if (p->p!=null) p->p->setc(x,p->dir()); else x->p=null;
p->setc(x->ch[d^1],d); x->setc(p,d^1); p->update(); x->update(); swap(x->fat,p->fat); swap(x->val,p->val);
}
node *sta[N];
void splay(node *x){
node *y=x; int pnt=0;
while (y!=null) sta[++pnt]=y,y=y->p;
for (int i=pnt;i;i--) sta[i]->pushdown(null);
while (x->p!=null)
if (x->p->p==null)
rot(x);
else
x->dir()==x->p->dir()?(rot(x->p),rot(x)):(rot(x),rot(x));
}
node *Access(node *x){
node *y=null;
while (x!=null){
splay(x);
if (x->ch[1]!=null){
int k=x->ch[0]->size+2;
pt t=Val.findkth(x->val,k);
Val.splay(t);
pt vv=t->ch[0];
x->ch[1]->val=t; x->ch[1]->p=null; x->ch[1]->fat=x;
t->ch[0]->p=Val.null; t->ch[0]=Val.null; t->update();
Val.splay(x->val=vv);
}
if (y!=null){
int k=x->val->size;
pt t=Val.findkth(x->val,k);
Val.splay(t);
t->setc(y->val,1); t->update();
y->val=0;
Val.splay(x->val);
}
x->setc(y,1); y->fat=null;
x->update();
y=x; x=x->fat;
}
return y;
}
void makeroot(node *x){
node *z=Access(x);
z->reverse(); z->val->reverse();
}
void Link(node *x,node *y){
makeroot(y);
splay(y);
y->fat=x;
Access(y);
}
void Rev(node *x,node *y){
makeroot(x);
Access(y)->val->reverse();
}
void Add(node *x,node *y,int v){
makeroot(x);
Access(y)->val->mark(v);
}
ll QSum(node *x,node *y){
makeroot(x);
return Access(y)->val->Sum;
}
ll QMax(node *x,node *y){
makeroot(x);
return Access(y)->val->Max;
}
ll QMin(node *x,node *y){
makeroot(x);
return Access(y)->val->Min;
}
void print(node *x){
if (x==null) return;
dprintf("%d",x->idx);
x->pushdown(null);
dprintf("("); print(x->ch[0]); dprintf(")");
dprintf("("); print(x->ch[1]); dprintf(")");
}
void Print(int n){
for (int i=1;i<=n;i++)
if (Mem[i].p==null)
print(Mem+i),dprintf("\n");
dprintf("\n");
}
}LCT;
int n;
T2::node *pos[N];
pt pos1[N];
inline void Pre(){
for (int i=1;i<=n;i++)
pos1[i]=Val.Mem+i;
for (int i=1;i<=n;i++){
pos[i]=LCT.Mem+i; pos[i]->p=pos[i]->ch[0]=pos[i]->ch[1]=pos[i]->fat=LCT.null;
pos[i]->idx=i;
pos[i]->size=1; pos[i]->val=Val.Mem+i;
pos[i]->val->size=1;
pos[i]->val->p=pos[i]->val->ch[0]=pos[i]->val->ch[1]=Val.null;
}
}
int main(){
int Q,R,ix,iy,iz; char order[10];
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
read(n); read(Q); read(R); Pre();
for (int i=1;i<n;i++)
read(ix),read(iy),LCT.Link(pos[iy],pos[ix]);
// LCT.Print(n);
while (Q--){
read(order); read(ix); read(iy);
if (!strcmp(order+1,"Increase")){
read(iz); LCT.Add(pos[ix],pos[iy],iz);
}else if (!strcmp(order+1,"Sum")){
printf("%lld\n",LCT.QSum(pos[ix],pos[iy]));
}else if (!strcmp(order+1,"Major")){
printf("%lld\n",LCT.QMax(pos[ix],pos[iy]));
}else if (!strcmp(order+1,"Minor")){
printf("%lld\n",LCT.QMin(pos[ix],pos[iy]));
}else if (!strcmp(order+1,"Invert")){
LCT.Rev(pos[ix],pos[iy]);
}
}
return 0;
}