Description
Input
Output
Sample Input
4 6
0 1 2
2 1 3
2 2
1 3
2 2
2 3
2 1
1 3
Sample Output
0
3
0
4
Data Constraint
分析:
设
为根到
的距离,询问点到所有黑点之间的距离可以看做是
为黑点数。
然后所有的黑点 的 和很好求,询问点 的和为 ,也是很好求的,关键就是 。
我们可以把询问点 到根的路径的权值设为 ,其他的权值全为 ,那么所有黑点 到根的路径权值和就是 。换种想法,可以把所有点到根的路径的每条边权值(初值为 )都加上为 ,那么 到根的路径和也是 。设每条边的权值设为 ,我们就相当于每次给一条路径上的所有 加 ,树剖+线段树维护即可。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
const int maxn=1e5+7;
using namespace std;
LL dis[maxn],sumd;
int top[maxn],size[maxn],dep[maxn],fa[maxn],dfn[maxn],ls[maxn];
bool vis[maxn];
int n,m,x,y,cnt;
struct node{
LL data,sum;
LL lazy;
}t[maxn*4];
struct edge{
int y,next;
LL w;
}g[maxn*2];
void dfs1(int x,int f)
{
fa[x]=f;
size[x]=1;
dep[x]=dep[f]+1;
for (int i=ls[x];i>0;i=g[i].next)
{
int y=g[i].y;
if (y==f) continue;
dis[y]=dis[x]+g[i].w;
dfs1(y,x);
size[x]+=size[y];
}
}
void dfs2(int x,int f)
{
dfn[x]=++cnt;
top[x]=f;
int c=1e5+1;
for (int i=ls[x];i>0;i=g[i].next)
{
int y=g[i].y;
if (y==fa[x]) continue;
if (size[c]<size[y]) c=y;
}
if (c==1e5+1) return;
dfs2(c,f);
for (int i=ls[x];i>0;i=g[i].next)
{
int y=g[i].y;
if ((y==fa[x]) || (y==c)) continue;
dfs2(y,y);
}
}
void build(int p,int l,int r,int x,int k)
{
if (l==r)
{
t[p].data=k;
return;
}
int mid=(l+r)/2;
if (x<=mid) build(p*2,l,mid,x,k);
else build(p*2+1,mid+1,r,x,k);
t[p].data=t[p*2].data+t[p*2+1].data;
}
void ins(int p,int l,int r,int x,int y,int k)
{
if ((l==x) && (r==y))
{
t[p].lazy+=1;
t[p].sum+=t[p].data;
return;
}
int mid=(l+r)/2;
if (t[p].lazy)
{
t[p*2].lazy+=t[p].lazy;
t[p*2].sum+=t[p*2].data*t[p].lazy;
t[p*2+1].lazy+=t[p].lazy;
t[p*2+1].sum+=t[p*2+1].data*t[p].lazy;
t[p].lazy=0;
}
if (y<=mid) ins(p*2,l,mid,x,y,k);
else
{
if (x>mid) ins(p*2+1,mid+1,r,x,y,k);
else
{
ins(p*2,l,mid,x,mid,k);
ins(p*2+1,mid+1,r,mid+1,y,k);
}
}
t[p].sum=t[p*2].sum+t[p*2+1].sum;
}
LL getsum(int p,int l,int r,int x,int y)
{
if ((l==x) && (r==y)) return t[p].sum;
int mid=(l+r)/2;
if (t[p].lazy)
{
t[p*2].lazy+=t[p].lazy;
t[p*2].sum+=t[p*2].data*t[p].lazy;
t[p*2+1].lazy+=t[p].lazy;
t[p*2+1].sum+=t[p*2+1].data*t[p].lazy;
t[p].lazy=0;
}
if (y<=mid) return getsum(p*2,l,mid,x,y);
else
{
if (x>mid) return getsum(p*2+1,mid+1,r,x,y);
else return getsum(p*2,l,mid,x,mid)+getsum(p*2+1,mid+1,r,mid+1,y);
}
}
void change(int x,int y)
{
while (top[x]!=top[y])
{
if (dep[top[x]]>dep[top[y]]) swap(x,y);
ins(1,1,n,dfn[top[y]],dfn[y],1);
y=fa[top[y]];
}
if (dep[x]>dep[y]) swap(x,y);
ins(1,1,n,dfn[x],dfn[y],1);
}
LL ask(int x,int y)
{
LL ans=dis[y]*cnt+sumd;
while (top[x]!=top[y])
{
if (dep[top[x]]>dep[top[y]]) swap(x,y);
ans-=2*getsum(1,1,n,dfn[top[y]],dfn[y]);
y=fa[top[y]];
}
if (dep[x]>dep[y]) swap(x,y);
ans-=2*getsum(1,1,n,dfn[x],dfn[y]);
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<n;i++)
{
scanf("%d",&x);
g[i].y=i;
g[i].next=ls[x];
ls[x]=i;
}
for (int i=1;i<n;i++) scanf("%d",&g[i].w);
dfs1(0,0);
cnt=0;
dfs2(0,0);
for (int i=0;i<n;i++) build(1,1,n,dfn[i],g[i].w);
cnt=0;
for (int i=1;i<=m;i++)
{
scanf("%d%d",&x,&y);
if (x==1)
{
if (!vis[y])
{
vis[y]=1;
sumd+=dis[y];
cnt++;
change(0,y);
}
}
else printf("%lld\n",ask(0,y));
}
}