正解應該是啓發式合併
#include <stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn = 200000+10;
#define inf 1000000007
int w[maxn],an[maxn];
int N, Q;
ll ans;
struct
{
int to,next,w;
}e[maxn<<2];
int head[maxn<<1],edgeNum;
struct
{
int u,v;
}edge[maxn<<1];
void add(int u,int v)
{
e[edgeNum].next = head[u];
e[edgeNum].to = v;
// e[edgeNum].w=w;
head[u] = edgeNum++;
}
/*-------------------------樹剖------------------------------*/
int deep[maxn],fa[maxn],siz[maxn],son[maxn];
void dfs1(int u,int pre,int d)
{
deep[u] = d;
//fa[u] = pre;
siz[u] = 1;
son[u] = 0;
for(int i=head[u];~i;i=e[i].next)
{
int v = e[i].to;
if(v!=pre)
{
dfs1(v,u,d+1);
siz[u] += siz[v];
if(siz[v]>siz[son[u]])
son[u] = v;
}
}
}
int top[maxn],id[maxn],rk[maxn],cnt;
void dfs2(int u,int t)
{
top[u] = t;
id[u] = ++cnt;
rk[cnt] = u;
if(!son[u]) return;
dfs2(son[u],t);
for(int i=head[u];~i;i=e[i].next)
{
int v = e[i].to;
if(v!=son[u])
dfs2(v,v);
}
}
/*-------------------------樹剖------------------------------*/
/*-------------------------線段樹------------------------------*/
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
ll sum[maxn<<2];
int maxid[maxn<<2];
ll lazy[maxn<<2];
void pushup(int rt)
{
int ls=rt<<1,rs=ls|1;
//sum[rt] = (sum[rt<<1] + sum[rt<<1|1]);
sum[rt]=max(sum[ls],sum[rs]);
if(sum[ls]>sum[rs])maxid[rt]=maxid[ls];//!
else maxid[rt]=maxid[rs];
}
void pushdown(int rt,int l,int r)
{
if(lazy[rt])
{
lazy[rt<<1] += ( lazy[rt]);
lazy[rt<<1|1] += ( lazy[rt]);
sum[rt<<1] += (lazy[rt] );
sum[rt<<1|1]+= (lazy[rt] );
lazy[rt] = 0;
}
}
//void build(int i,int l,int r)
//{
// if (l==r) {t[i].sum=w[rk[l]];t[i].maxid=rk[l];return;}
// int mid=(l+r)>>1,ls=i<<1,rs=ls|1;
// build(ls,l,mid);build(rs,mid+1,r);
// pushup(i);
//}
void change(int val,int q,int l,int r,int rt)//單點更新
{
if(l==r)
{
sum[rt] = val;
maxid[rt]=rk[l];
return ;
}
int m = l + r >> 1;
if(q<=m)
change(val,q,lson);
else
change(val,q,rson);
pushup(rt);
}
void update(int L,int R,int val,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
sum[rt] = (sum[rt]+ val) ;
lazy[rt] = lazy[rt]+val;
return ;
}
int m = l + r >> 1;
pushdown(rt,m-l+1,r-m);
if(L<=m)
update(L,R,val,lson);
if(R>m)
update(L,R,val,rson);
pushup(rt);
}
/*-------------------------線段樹------------------------------*/
/*-----------------------樹剖加線段樹--------------------------*/
void Update(int x,int y) {
while(x){
update(id[top[x]],id[x],y,1,N,1);
x=fa[top[x]];
}
}
/*-----------------------樹剖加線段樹--------------------------*/
void init()
{
memset(head,-1,4*N+4);
cnt = edgeNum = 0;
}
int u, v, o,z,cur;
int main()
{
scanf("%d",&N);
init();
for(int i=1;i<=N;i++)scanf("%d",&w[i]);
for(int i=2;i<=N;++i)
{
scanf("%d",&fa[i]);
add(fa[i],i);//邊數*2
//add(i,fa[i]);
}
dfs1(1,0,1);
dfs2(1,1);
//build(1,1,N);
for(int i=1;i<=N;i++){
// int tmp=deep[edge[i].u] > deep[edge[i].v] ? edge[i].u : edge[i].v;
change(w[i],id[i],1,N,1);
}
while(sum[1]>0){
int max1=0,k=0;
while(sum[1]>0){
//cout<<t[1].sum<<endl;
int x=maxid[1];
if(sum[1]>max1)max1=sum[1];
an[++k]=x;
update(id[x],id[x]+siz[x]-1,-inf,1,N,1);
Update(fa[x],-inf);
}
ans+=max1;
for(int i=1;i<=k;i++){
int x=an[i];
update(id[x],id[x]+siz[x]-1,inf,1,N,1);
Update(fa[x],inf);
}
for(int i=1;i<=k;i++){
int x=an[i];
update(id[x],id[x],-inf,1,N,1);
}
}
printf("%lld\n",ans);
return 0;
}