ETT搞上,每条边如果是一条从父到子的边,那么设其权值为儿子节点的权值,如果是一条从子到父的边,那么设其权值为儿子节点的权值的相反数,我们用一个splay来维护整棵树的欧拉序,那么一个节点到根的路径的点权和就等于从根走欧拉序到这个点的边权和
linkcut操作就相当于区间平移
子树加就相当于把区间里父到子的边加,子到父的边减
维护区间和
就过了
注意w[i]开始可以得0
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
using namespace std;
#define MAXN 200010
#define MAXM 1010
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
#define ll long long
#define tr son[son[rt][1]][0]
struct vec{
int to;
int fro;
};
vec mp[MAXN];
int tai[MAXN],cnt;
int w[MAXN];
int s[MAXN],t[MAXN];
int a[MAXN],tim;
int rt;
int st[MAXN],tp;
int fa[MAXN],son[MAXN][2];
ll v[MAXN],ch[MAXN],sum[MAXN],siz[MAXN];
int typ[MAXN];
int n,m;
inline void be(int x,int y){
mp[++cnt].to=y;
mp[cnt].fro=tai[x];
tai[x]=cnt;
}
inline void ud(int x){
sum[x]=sum[son[x][0]]+sum[son[x][1]]+v[x];
siz[x]=siz[son[x][0]]+siz[son[x][1]]+typ[x];
}
inline void toch(int x,ll y){
if(!x){
return ;
}
sum[x]+=siz[x]*y;
if(typ[x]==1){
v[x]+=y;
}
if(typ[x]==-1){
v[x]-=y;
}
ch[x]+=y;
}
inline void pd(int x){
if(ch[x]){
toch(son[x][0],ch[x]);
toch(son[x][1],ch[x]);
ch[x]=0;
}
}
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);
cot(x,xxx,son[xxx][1]==xx);
cot(xx,x,z);
ud(xx);
}
void dfs(int x){
int i,y;
a[s[x]=++tim]=w[x];
typ[tim]=1;
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
dfs(y);
}
a[t[x]=++tim]=-w[x];
typ[tim]=-1;
}
void build(int &x,int l,int r,int f){
if(l>r){
return ;
}
int mid=l+r>>1;
x=mid;
fa[x]=f;
v[x]=a[x];
build(son[x][0],l,mid-1,x);
build(son[x][1],mid+1,r,x);
ud(x);
}
inline void apd(int x){
for(;x;x=fa[x]){
st[++tp]=x;
}
for(;tp;tp--){
pd(st[tp]);
}
}
void splay(int x,int y){
apd(x);
int xx=fa[x],xxx=fa[xx];
while(xx!=y){
if(xxx==y){
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);
}
}
xx=fa[x],xxx=fa[xx];
}
ud(x);
if(!y){
rt=x;
}
}
int findp(int x){
splay(x,0);
x=son[x][0];
while(son[x][1]){
x=son[x][1];
}
return x;
}
int findn(int x){
splay(x,0);
x=son[x][1];
while(son[x][0]){
x=son[x][0];
}
return x;
}
int main(){
int i,x,y;
char o[2];
scanf("%d",&n);
for(i=2;i<=n;i++){
scanf("%d",&x);
be(x,i);
}
for(i=1;i<=n;i++){
scanf("%d",&w[i]);
}
a[++tim]=0;
dfs(1);
a[++tim]=0;
build(rt,1,tim,0);
scanf("%d",&m);
while(m--){
scanf("%s",o);
if(o[0]=='Q'){
scanf("%d",&x);
splay(s[x],0);
printf("%lld\n",sum[son[rt][0]]+v[rt]);
}
if(o[0]=='F'){
scanf("%d%d",&x,&y);
int X=findp(s[x]);
int Y=findn(t[x]);
splay(X,0);
splay(Y,rt);
toch(tr,y);
}
if(o[0]=='C'){
scanf("%d%d",&x,&y);
int X=findp(s[x]);
int Y=findn(t[x]);
splay(X,0);
splay(Y,rt);
int tmp=tr;
tr=0;
ud(son[rt][1]);
ud(rt);
X=findp(t[y]);
splay(X,0);
splay(t[y],rt);
tr=tmp;
fa[tmp]=son[rt][1];
ud(son[rt][1]);
ud(rt);
}
}
return 0;
}
/*
3
1
1
4 5 7
5
Q 2
F 1 3
Q 2
C 2 3
Q 2
*/