题解:
考试时只会70分的
的做法,就直接点分治,对每个重心
维护一个
的前缀和,可以用数据结构维护。但是我们发现在下一层,我们所需要的答案只会减少一个值,所以就可以不同数据结构维护,做到
。
注意离开一颗子树后要消除它的影响。
代码:
#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
int num[30];
void write(LL x)
{
if(!x)putchar('0');
else
{
int l=0;
while(x)num[++l]=x%10LL,x/=10LL;
for(int i=l;i;i--)putchar(num[i]+48);
}
putchar('\n');
}
const int Maxn=200010,Maxm=500010;
int n,m;
struct Edge{int y,next;}e[Maxn<<1];
int last[Maxn],len=0;
void ins(int x,int y){int t=++len;e[t].y=y;e[t].next=last[x];last[x]=t;}
vector<int>h[Maxn];
LL ans[Maxn];
int root,son[Maxn],totsize;
bool del[Maxn];
LL s[Maxn],sums=0;int S[Maxn],sumS=0;
// 权值和 个数
int get_size(int x,int fa)
{
int size=1;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==fa||del[y])continue;
size+=get_size(y,x);
}
return size;
}
int get_root(int x,int fa)
{
int size=1,mx=0;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==fa||del[y])continue;
int t=get_root(y,x);
mx=max(mx,t);size+=t;
}
son[x]=max(mx,totsize-size);
if(root==-1)root=x;
else if(son[x]<son[root])root=x;
return size;
}
int mxdep;
void dfs(int x,int fa,int depth,LL o)
{
for(int i=0;i<h[x].size();i++)
{
int power=h[x][i],t=power-depth;
if(t>0)
{
int k=t;
if(t>n)k=n;
sums+=(LL)t*o;s[k]+=(LL)t*o;
sumS+=o;S[k]+=o;
}
}
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==fa||del[y])continue;
dfs(y,x,depth+1,o);
}
}
LL ts;int tS;
void DFS(int x,int fa,int depth)
{
if(depth)ts-=s[depth-1],tS-=S[depth-1];
ans[x]+=ts-tS*(LL)(depth);
LL tmps=ts;int tmpS=tS;
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==fa||del[y])continue;
ts=tmps,tS=tmpS;
DFS(y,x,depth+1);
}
}
void dfs_mark(int x,int fa,int depth)
{
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==fa||del[y])continue;
DFS(y,x,depth+1);
}
}
void DFS_x(int x,int fa,int depth,int rt)
{
for(int i=0;i<h[x].size();i++)
{
int power=h[x][i],t=power-depth;
if(t>0)ans[rt]+=(LL)t;
}
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(y==fa||del[y])continue;
DFS_x(y,x,depth+1,rt);
}
}
void calc(int x)
{
DFS_x(x,0,0,x);
dfs(x,0,0,1);
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(del[y])continue;
dfs(y,x,1,-1);
ts=sums,tS=sumS;
DFS(y,x,1);
dfs(y,x,1,1);
}
dfs(x,0,0,-1);
}
int Fa[Maxn];
void solve(int x)
{
del[x]=true;
calc(x);
for(int i=last[x];i;i=e[i].next)
{
int y=e[i].y;
if(del[y])continue;
root=-1;
totsize=get_size(y,x);
get_root(y,x);Fa[root]=x;
solve(root);
}
}
int main()
{
n=read(),m=read();
for(int i=2;i<=n;i++)
{
int Fa=read();
ins(Fa,i),ins(i,Fa);
}
for(int i=1;i<=m;i++)
{
int pos=read(),power=read();
h[pos].push_back(power);
}
root=-1;
totsize=n;
get_root(1,0);
solve(root);
for(int i=1;i<=n;i++)write(ans[i]);
}