因为LCT只能将路径上的点翻转而不是权值,所以不能直接用LCT做。
考虑再建一棵LCT维护权值。
查询原Splay第k个数的权值时在第二棵Splay中查找。
进行翻转操作直接将第二个LCT翻转就可以了。
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void Read(int& x){
char c=nc();
for(;c<'0'||c>'9';c=nc());
for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());
}
inline void Read(char* s){
char c=nc();
for(;!((c>='a'&&c<='z')||(c>='A'&&c<='Z'));c=nc());
for(int j=0;(c>='a'&&c<='z')||(c>='A'&&c<='Z');s[j++]=c,c=nc());
}
#define N 50010
#define ll long long
int i,j,k,n,m,x,y,z;
char s[30];
struct Splay1{
int f[N],rt[N],ch[N][2],s[N];
bool b[N],r[N];
inline bool Get(int x){
return ch[f[x]][1]==x;
}
inline void Update_rev(int x){
if(!x)return;
r[x]^=1;swap(ch[x][0],ch[x][1]);
}
inline void Down(int x){
if(!x)return;
if(r[x])Update_rev(ch[x][0]),Update_rev(ch[x][1]),r[x]=0;
}
inline void Up(int x){
if(!x)return;
s[x]=s[ch[x][0]]+s[ch[x][1]]+1;
}
inline void Rotate(int x){
bool d=Get(x);int y=f[x];
if(b[y])b[x]=1,b[y]=0,rt[x]=rt[y];else ch[f[y]][Get(y)]=x;
ch[y][d]=ch[x][d^1];f[ch[y][d]]=y;
f[x]=f[y];f[y]=x;ch[x][d^1]=y;Up(y);
}
inline void P(int x){
if(!b[x])P(f[x]);
Down(x);
}
inline void Splay(int x){
for(P(x);!b[x];Rotate(x))
if(!b[f[x]])Rotate(Get(x)==Get(f[x])?f[x]:x);
Up(x);
}
}fm;
struct Splay2{
ll sum[N];
int f[N],s[N],ch[N][2],ma[N],mi[N],a[N],p[N];
bool b[N],r[N];
inline bool Get(int x){
return ch[f[x]][1]==x;
}
inline void Update_rev(int x){
if(!x)return;
r[x]^=1;swap(ch[x][0],ch[x][1]);
}
inline void Update_add(int x,int y){
if(!x)return;
p[x]+=y;sum[x]+=1ll*y*s[x];a[x]+=y;
ma[x]+=y;mi[x]+=y;
}
inline void Up(int x){
if(!x)return;
s[x]=s[ch[x][0]]+s[ch[x][1]]+1;
sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+a[x];
ma[x]=max(a[x],max(ma[ch[x][0]],ma[ch[x][1]]));
mi[x]=min(a[x],min(mi[ch[x][0]],mi[ch[x][1]]));
}
inline void Down(int x){
if(!x)return;
if(p[x]){
Update_add(ch[x][0],p[x]);Update_add(ch[x][1],p[x]);
p[x]=0;
}
if(r[x])Update_rev(ch[x][0]),Update_rev(ch[x][1]),r[x]=0;
}
inline void Rotate(int x){
bool d=Get(x);int y=f[x];
if(b[y])b[x]=1,b[y]=0;else ch[f[y]][Get(y)]=x;
ch[y][d]=ch[x][d^1];f[ch[y][d]]=y;
f[x]=f[y];f[y]=x;ch[x][d^1]=y;Up(y);
}
inline void P(int x){
if(!b[x])P(f[x]);
Down(x);
}
inline void Splay(int x){
for(P(x);!b[x];Rotate(x))
if(!b[f[x]])Rotate(Get(x)==Get(f[x])?f[x]:x);
Up(x);
}
inline int Find(int x,int y){
y-=s[ch[x][0]]+1;
if(!y)return x;
Down(x);
if(y<0)return Find(ch[x][0],y+s[ch[x][0]]+1);
return Find(ch[x][1],y);
}
}vl;
inline void Access(int x){
int y=0;
while(x){
fm.Splay(x);
int z=fm.rt[x];
vl.Splay(z);
z=vl.Find(z,fm.s[fm.ch[x][0]]+1);
vl.Splay(z);
fm.b[fm.ch[x][1]]=vl.b[vl.ch[z][1]]=1;
fm.b[y]=vl.b[fm.rt[y]]=0;
fm.rt[fm.ch[x][1]]=vl.ch[z][1];
vl.f[vl.ch[z][1]]=0;
vl.f[fm.rt[y]]=z;
fm.ch[x][1]=y;vl.ch[z][1]=fm.rt[y];
fm.rt[x]=z;
fm.Up(y=x);vl.Up(z);
x=fm.f[x];
}
}
inline void mr(int x){
Access(x);fm.Splay(x);vl.Splay(fm.rt[x]);
fm.Update_rev(x);vl.Update_rev(fm.rt[x]);
}
inline void Link(int x,int y){
mr(x);fm.f[x]=y;
}
inline void mt(int x,int y){
mr(x);Access(y);fm.Splay(y);vl.Splay(fm.rt[y]);
}
int main(){
Read(n);Read(m);Read(x);
vl.mi[0]=2147483647;vl.ma[0]=-2147483647;
for(i=1;i<=n;i++)fm.b[i]=vl.b[i]=fm.s[i]=vl.s[i]=1,fm.rt[i]=i;
for(i=1;i<n;i++)Read(x),Read(y),Link(x,y);
while(m--){
Read(s);Read(x);Read(y);
mt(x,y);
if(s[0]=='I'&&s[2]=='c')Read(z),vl.Update_add(fm.rt[y],z);else
if(s[0]=='S')printf("%lld\n",vl.sum[fm.rt[y]]);else
if(s[0]=='I'&&s[2]=='v')vl.Update_rev(fm.rt[y]);else
if(s[1]=='a')printf("%d\n",vl.ma[fm.rt[y]]);else printf("%d\n",vl.mi[fm.rt[y]]);
}
return 0;
}