bzoj真是坑爹,本地跑的差不多的程序,指针比数组快到不知道哪里去了。
然后我就开始了艰辛的卡常数,最终比很多指针快多辣~~~
由于有子树移动,那么考虑维护括号序列。也就是dfs入栈为'(',出栈为')',然后'('为正的权值。那么子树移动相当于平衡树的分裂和合并。用splay实现。
PS:求卡常数大神优化代码>.<
AC代码如下(目前最快的):
#include<bits/stdc++.h>
#define ll long long
#define N 200005
using namespace std;
int n,tot,tp,rt,a[N],fst[N],pnt[N],nxt[N],fa[N],c[N][2],q[N];
struct node{ int sz,sc; ll icr,num,sum; }P[N];
int read(){
int x=0; char cr=getchar();
while (cr<'0' || cr>'9') cr=getchar();
while (cr>='0' && cr<='9'){ x=x*10+cr-'0'; cr=getchar(); }
return x;
}
void add(int x,int y){
pnt[++tot]=y; nxt[tot]=fst[x]; fst[x]=tot;
}
void maintain(int x){
node &o=P[x],&l=P[c[x][0]],&r=P[c[x][1]];
o.sz=l.sz+r.sz+1; o.sc=l.sc+r.sc+((x<=n)?1:-1);
o.sum=l.sum+r.sum+o.num;
}
void mdy(int x,ll y){
if (x){
node &o=P[x];
o.icr+=y; o.num+=(x<=n)?y:-y; o.sum+=o.sc*y;
}
}
void pushdn(int x){
ll &t=P[x].icr;
if (t){
mdy(c[x][0],t); mdy(c[x][1],t); t=0;
}
}
void clr(int x){
int i; q[tp=1]=x;
for (i=x; i!=rt; i=fa[i]) q[++tp]=fa[i];
while (tp) pushdn(q[tp--]);
}
int getby(int x,int l){
int r=l^1;
if (c[x][l]){
for (x=c[x][l]; c[x][r]; x=c[x][r]); return x;
} else{
int y;
for (y=fa[x]; y && c[y][l]==x; x=y,y=fa[y]); return y;
}
}
void rot(int x,int &rt){
int y=fa[x],z=fa[y],l=(c[y][1]==x),r=l^1;
if (y!=rt) c[z][c[z][1]==y]=x; else rt=x;
fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
c[y][l]=c[x][r]; c[x][r]=y;
maintain(y);
}
void splay(int x,int &rt){
int i,y,z; clr(x);
for (; x!=rt; rot(x,rt)){
y=fa[x]; z=fa[y];
if (y!=rt) rot((c[z][0]==y ^ c[y][0]==x)?x:y,rt);
}
maintain(x);
}
void dfs(int x,int last){
int i,y; q[++tp]=x;
for (i=fst[x]; i; i=nxt[i]){
y=pnt[i];
if (y!=last) dfs(y,x);
}
q[++tp]=x+n;
}
void build(int &rt,int l,int r,int last){
if (l>r){ rt=0; return; }
int mid=l+r>>1;
rt=q[mid]; fa[rt]=last;
build(c[rt][0],l,mid-1,rt); build(c[rt][1],mid+1,r,rt);
P[rt].num=(rt<=n)?a[rt]:-a[rt-n];
maintain(rt);
}
int main(){
n=read();
int i,x,y,l,r;
for (i=2; i<=n; i++){
x=read(); add(x,i); add(i,x);
}
for (i=1; i<=n; i++) a[i]=read();
q[tp=1]=n<<1|1;
dfs(1,0);
q[++tp]=n+1<<1;
build(rt,1,tp,0);
int cas=read(); char cr; ll ans;
while (cas--){
cr=getchar(); while (cr<'A' || cr>'Z') cr=getchar();
if (cr=='Q'){
x=read(); clr(x);
ans=P[c[x][0]].sum+P[x].num;
for (y=fa[x]; x!=rt; x=y,y=fa[y])
if (x==c[y][1]) ans+=P[c[y][0]].sum+P[y].num;
printf("%lld\n",ans);
} else if (cr=='C'){
x=read(); y=read();
l=getby(x,0); r=getby(x+n,1);
splay(l,rt); splay(r,c[l][1]);
x=c[r][0]; c[r][0]=0;
maintain(r); maintain(l);
splay(y,rt); r=getby(y,1); splay(r,c[y][1]);
fa[x]=r; c[r][0]=x;
maintain(r); maintain(y);
} else if (cr=='F'){
x=read();
y=getby(x+n,1); x=getby(x,0);
splay(x,rt); splay(y,c[x][1]);
mdy(c[y][0],read());
}
}
return 0;
}
by lych
2016.12.6