3091双倍经验
把3091代码粘过来然后边权转点权就好了
……知识点分到LCT里是不是不太好啊
#include<iostream>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<cstdlib>
#include<cstdio>
#include<map>
#include<bitset>
#include<set>
#include<stack>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 100010
#define MAXM 1010
#define ll long long
#define eps 1e-8
#define MOD 1000000000
#define INF 1000000007
int fa[MAXN],son[MAXN][2];
bool rev[MAXN];
int st[MAXN],tp;
ll siz[MAXN],sa[MAXN],sl[MAXN],sr[MAXN],slr[MAXN],slra[MAXN],sla[MAXN],sra[MAXN],ch[MAXN],a[MAXN];
int n,m;
ll gcd(ll x,ll y){
return !y?x:gcd(y,x%y);
}
inline void torev(int x){
if(!x){
return ;
}
swap(son[x][0],son[x][1]);
swap(sl[x],sr[x]);
swap(sla[x],sra[x]);
rev[x]^=1;
}
inline void toch(int x,ll y){
if(!x){
return ;
}
a[x]+=y;
ch[x]+=y;
slra[x]+=slr[x]*y;
sla[x]+=sl[x]*y;
sra[x]+=sr[x]*y;
sa[x]+=siz[x]*y;
}
inline void ud(int x){
slra[x]=slra[son[x][0]]+slra[son[x][1]]+
sla[son[x][0]]*(siz[son[x][1]]+1)+
sra[son[x][1]]*(siz[son[x][0]]+1)+
siz[son[x][0]]*siz[son[x][1]]*a[x]
;
sla[x]=sla[son[x][0]]+sla[son[x][1]]+(siz[son[x][0]]+1)*sa[son[x][1]]+siz[son[x][0]]*a[x];
sra[x]=sra[son[x][1]]+sra[son[x][0]]+(siz[son[x][1]]+1)*sa[son[x][0]]+siz[son[x][1]]*a[x];
sa[x]=sa[son[x][0]]+sa[son[x][1]]+a[x];
siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;
sl[x]=sl[son[x][0]]+sl[son[x][1]]+(siz[son[x][0]]+1)*siz[son[x][1]]+siz[son[x][0]];
sr[x]=sr[son[x][1]]+sr[son[x][0]]+(siz[son[x][1]]+1)*siz[son[x][0]]+siz[son[x][1]];
slr[x]=slr[son[x][0]]+slr[son[x][1]]+sl[son[x][0]]*(siz[son[x][1]]+1)+sr[son[x][1]]*(siz[son[x][0]]+1)+siz[son[x][0]]*siz[son[x][1]];
}
inline void pd(int x){
if(rev[x]){
torev(son[x][0]);
torev(son[x][1]);
rev[x]=0;
}
if(ch[x]){
toch(son[x][0],ch[x]);
toch(son[x][1],ch[x]);
ch[x]=0;
}
}
inline bool ir(int x){
return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;
}
inline void cot(int x,int y,bool z){
if(x){
fa[x]=y;
}
if(y){
son[y][z]=x;
}
}
inline void rot(int x,bool z){
int xx=fa[x],xxx=fa[xx];
cot(son[x][z],xx,z^1);
if(ir(xx)){
fa[x]=xxx;
}else{
cot(x,xxx,son[xxx][1]==xx);
}
cot(xx,x,z);
ud(xx);
}
inline void apd(int x){
int i;
st[++tp]=x;
for(i=x;!ir(i);i=fa[i]){
st[++tp]=fa[i];
}
for(;tp;tp--){
pd(st[tp]);
}
}
void splay(int x){
apd(x);
while(!ir(x)){
int xx=fa[x],xxx=fa[xx];
if(ir(xx)){
rot(x,son[xx][0]==x);
}else{
bool z=son[xxx][0]==xx;
if(son[xx][z]==x){
rot(x,z^1);
rot(x,z);
}else{
rot(xx,z);
rot(x,z);
}
}
}
ud(x);
}
inline void acs(int x){
int t=0;
while(x){
splay(x);
son[x][1]=t;
ud(x);
t=x;
x=fa[x];
}
}
inline void reboot(int x){
acs(x);
splay(x);
torev(x);
}
inline void link(int x,int y){
reboot(x);
fa[x]=y;
}
inline void cut(int x,int y){
reboot(x);
acs(y);
splay(y);
if(siz[y]==2){
son[y][0]=fa[x]=0;
ud(y);
}
}
int rt(int x){
acs(x);
splay(x);
pd(x);
while(son[x][0]){
x=son[x][0];
pd(x);
}
return x;
}
int main(){
int i,x,y,z;
char o[2];
scanf("%d%d",&n,&m);
n--;
for(i=1;i<=n;i++){
ud(i);
}
for(i=1;i<n;i++){
link(i,i+1);
}
while(m--){
scanf("%s",o);
if(o[0]=='C'){
scanf("%d%d%d",&x,&y,&z);
y--;
reboot(x);
acs(y);
splay(y);
toch(y,z);
}
if(o[0]=='Q'){
scanf("%d%d",&x,&y);
y--;
reboot(x);
acs(y);
splay(y);
ll t=slra[y]+siz[y]*sa[y];
ll c=siz[y]*(siz[y]+1)/2;
ll g=gcd(t,c);
printf("%lld/%lld\n",t/g,c/g);
}
}
return 0;
}
/*
4 5
C 1 4 2
C 1 2 -1
Q 1 2
Q 2 4
Q 1 4
*/