咋一眼看过去,那么像动态点分治…
大概想一下代码量,嗯…,不少…
那么来想一下树链剖分怎么打,
设一根节点的距离是c,与根的路径为s,
点x,y之间的距离也就是 cx+cy−2∗CLCA(x,y) ,
那么我们只需要动态维护LCA即可,
在一条树链中,点x与所有与根的路径经过这条链的点的LCA和分两个部分:在x上面进入链;在x下面进入点;
对于前者,LCA就是它们第一次进入链时的点的s,用树状数组统计所有点的和,
对于后者,LCA就是x点,还是用树状数组统计个数,乘一下即可;
复杂度: O(nlog(n)2)
#include<cstdio>
#include<cstdlib>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
#define NX(q) ((q)&(-(q)))
using namespace std;
typedef long long LL;
const int N=100500;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int n,m,m1,zx0;
int B[2*N][3],A[N],B0=1;
LL f[N][2];
struct qqww
{int fa,lt,zx,si,ld,lt1;LL c1;}a[N];
LL ans;
bool z[N];
void join(int q,int w,int e)
{
B[++B0][0]=A[q],A[q]=B0,B[B0][1]=w,B[B0][2]=e;
B[++B0][0]=A[w],A[w]=B0,B[B0][1]=q,B[B0][2]=e;
}
int dfs1(int q,int fa,int c1)
{
a[q].fa=fa;a[q].si=1;a[q].c1=c1;
efo(i,q)if(B[i][1]!=fa)a[q].si+=dfs1(B[i][1],q,c1+B[i][2]);
return a[q].si;
}
void dfs2(int q,int fa,int lt)
{
if(!lt)lt=q;
a[q].lt=lt;a[q].zx=++zx0;
int mx=0;
efo(i,q)if(fa!=B[i][1]&&a[B[i][1]].si>a[mx].si)mx=B[i][1];
if(mx)dfs2(mx,q,lt);else a[lt].ld=q;
efo(i,q)if(fa!=B[i][1]&&B[i][1]!=mx)dfs2(B[i][1],q,0);
}
LL find(int l,int r,int e)
{
if(r<l)return 0;
int q=r;LL ans=0;
while(q)ans+=f[q][e],q-=NX(q);
q=l-1;
while(q)ans-=f[q][e],q-=NX(q);
return ans;
}
void modify(int w)
{
int q=a[w].zx;
while(q<=n)f[q][1]+=a[w].c1,f[q][0]++,q+=NX(q);
}
LL find(int q)
{
int w,e=0;
LL ans=0;
while(w=a[q].lt)
{
ans+=find(a[w].zx,a[q].zx,1)+find(a[q].zx+1,a[a[w].ld].zx,0)*a[q].c1-e*a[q].c1;
e=a[w].lt1;q=a[w].fa;
}
return ans;
}
void change(int q)
{
int w;
while(w=a[q].lt)modify(q),a[w].lt1++,q=a[w].fa;
}
int main()
{
int q,w,e;
read(n),read(m1);
fo(i,2,n)read(a[i].fa);
fo(i,2,n)join(i,++a[i].fa,read(q));
dfs1(1,0,0);
dfs2(1,0,0);
ans=0;
while(m1--)
{
read(q),read(w);w++;
if(q-1)printf("%lld\n",ans-2*find(w)+m*a[w].c1);
else if(!z[w])change(w),z[w]=1,ans+=a[w].c1,m++;
}
return 0;
}