题目大意:n个点的树,m个操作
1.询问到根权值和
2.改变父亲,保证不出环
3.子树加
n<=100000,m<=300000,要开long long
toptree轻松虐,可惜我不会
因为本题的询问都是一个点到根的,根又不会变,因此可以通过维护入栈出栈序的方法,每个点入栈时向splay中push _ back一个正权值点,出栈时向splay中push _ back一个负权值点,这样从头到查询点之间的其它点会正负抵消。
改变父亲就将这个点入栈——出栈之间的一段提出来,插到父亲的入栈点之后。
入栈点cnt记为1,出栈点记为-1,则add标记对sum的增加量就是cnt之和*add,入栈点v+=add,出栈点v-=add。
注意权值有0,因此不能靠权值的正负来判断是入栈点还是出栈点,要单独记录。
#include<cstdio>
#define gm 100001
using namespace std;
typedef long long ll;
typedef const ll& cref;
struct node
{
ll sum,v,add;
char inv;
int cnt;
node *s[2],*f;
node();
node(cref,char);
inline void* operator new(size_t)
{
static unsigned char p[gm*sizeof(node)*2];
static size_t t=-1;
return ((node*)p)+ ++t;
}
inline bool r()
{
return this==f->s[1];
}
inline void up()
{
sum=v+s[0]->sum+s[1]->sum;
cnt=inv+s[0]->cnt+s[1]->cnt;
}
inline void plus(cref);
inline void down();
}*nil=new node;
node::node():sum(0),v(0),add(0),cnt(0),f(nil){s[0]=s[1]=nil;}
node::node(cref v,char inv):sum(v),v(v),add(0),inv(inv),cnt(inv),f(nil){s[0]=s[1]=nil;}
inline void node::plus(cref a)
{
if(this==nil) return;
add+=a;
if(~inv) v+=a;else v-=a;
sum+=cnt*a;
}
inline void node::down()
{
if(f!=nil) f->down();
if(add)
s[0]->plus(add),s[1]->plus(add),add=0;
}
struct SplayTree
{
typedef node* Iterator;
node *rt;
SplayTree(node *rt=nil):rt(rt){}
inline void rot(node *x)
{
static node *o,*y;
static bool k;
k=!x->r();
o=x->f,y=x->s[k];
if(o->f!=nil) o->f->s[o->r()]=x;
x->s[k]=o,o->s[!k]=y;
x->f=o->f,o->f=x,y->f=o;
o->up();
}
inline void splay(node *x)
{
x->down();
while(x->f!=nil)
{
if(x->f->f==nil) rot(x);
else if(x->r()==x->f->r()) rot(x->f),rot(x);
else rot(x),rot(x);
}
rt=x;
x->up();
}
inline void push_back(node *x)
{
if(rt==nil) {rt=x;return;}
node *now=rt;
while(now->s[1]!=nil) now=now->s[1];
splay(now);
now->s[1]=x;
x->f=now;
now->up();
}
inline node* push_back(cref v,char t)
{
node *x=new node(v,t);
push_back(x);
return x;
}
inline void push_back(SplayTree& v)
{
push_back(v.rt);
v.rt=nil;
}
inline SplayTree split_before(node *x)
{
splay(x);
x=rt->s[0];
rt->s[0]=x->f=nil;
rt->up();
return SplayTree(x);
}
inline SplayTree split_after(node *x)
{
splay(x);
x=rt->s[1];
rt->s[1]=x->f=nil;
rt->up();
return SplayTree(x);
}
inline void add(cref v)
{
rt->plus(v);
}
inline ll sum()
{
return rt->sum;
}
}tree;
int n,m,fat[gm],w[gm];
char c;
SplayTree::Iterator begin[gm],end[gm];
struct e
{
int t;
e *n;
e(int t,e *n):t(t),n(n){}
}*f[gm];
void dfs(int x)
{
begin[x]=tree.push_back(ll(w[x]),1);
for(e *i=f[x];i;i=i->n)
if(i->t!=fat[x])
dfs(i->t);
end[x]=tree.push_back(ll(-w[x]),-1);
}
inline ll query(int x)
{
SplayTree arc=tree.split_after(begin[x]);
ll ans=tree.sum();
tree.push_back(arc);
return ans;
}
inline void reset(int x,int y)
{
SplayTree pre=tree.split_before(begin[x]),arc=tree.split_after(end[x]);
pre.push_back(arc);
arc=pre.split_after(begin[y]);
tree.push_back(arc);
pre.push_back(tree);
tree.push_back(pre);
}
inline void add(int x,ll v)
{
SplayTree pre=tree.split_before(begin[x]),arc=tree.split_after(end[x]);
tree.add(v);
tree.push_back(arc);
pre.push_back(tree);
tree.push_back(pre);
}
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;++i)
{
scanf("%d",fat+i);
f[fat[i]]=new e(i,f[fat[i]]);
}
for(int i=1;i<=n;++i)
scanf("%d",w+i);
dfs(1);
scanf("%d",&m);
while(m--)
{
do c=getchar();while(c!='Q'&&c!='C'&&c!='F');
if(c=='Q')
{
int d;
scanf("%d",&d);
printf("%lld\n",query(d));
}
else if(c=='C')
{
int x,y;
scanf("%d%d",&x,&y);
reset(x,y);
}
else
{
int p,q;
scanf("%d%d",&p,&q);
add(p,q);
}
}
return 0;
}