emmm..

题意是计算每颗子树下,标号从小到大排列后,相邻项差值的平方和

涉及到静态子数问题, 就是经典解决方法了

维护了静态子数的信息,所以只需要处理新加入的权值 与 当前权值 的关系就好了

记得今年牛客2020多校有个三角形的加入边与删除边,维护最小差值的,与这个思路类似

首先把权值全部放入一个集合中,那么对于新加入的一个,它只会影响到

所以显然,用set考虑新来的元素在set中的三种位置,就可以处理权值的大小变化

Code:

/*** keep hungry and calm CoolGuang!  ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17+7;
const ll maxn = 2e5+700;
const ll mod= 1e9+7;
const double eps = 1e-8;
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
vector<int>v[maxn];
set<ll>s;
int sz[maxn],son[maxn];
ll res[maxn];
void dfs(int u){
    sz[u] = 1;
    for(int e:v[u]){
        dfs(e);
        sz[u] += sz[e];
        if(sz[son[u]] < sz[e]) son[u] = e;
    }
}
ll ans = 0;
ll gg(ll x){
    return x*x;
}
void add(ll x){
    if(!s.size()){
        s.insert(x);
        return;
    }
    auto u = s.lower_bound(x);
    if(u == s.begin()){
        ans = ans + gg(*u-x)*1ll;
    }
    else if(u == s.end()){
        u = prev(u),ans = ans + gg(*u-x)*1ll;
    }
    else{
        ll xx = *prev(u),y = *u;
        ans -= gg(xx-y)*1ll;
        ans += gg(xx-x)*1ll;
        ans += gg(y-x)*1ll;
    }
    s.insert(x);
}
void del(ll x){
    if(s.size() == 1){
        s.erase(x);
        return;
    }
    auto u = s.lower_bound(x);
    if(u == s.begin()) ans = ans - gg(x-(*next(u)))*1ll;
    else if(u == prev(s.end())) ans = ans - gg(x - (*prev(u)))*1ll;
    else{
        ll xx = *prev(u), y = *next(u);
        ans -= gg(xx-x)*1ll;
        ans -= gg(y-x)*1ll;
        ans += gg(xx-y)*1ll;
    } 
    s.erase(x);
    return;
}

void cal(int u,int f){
    if(f) add(u);
    else del(u);
    for(int e:v[u]) cal(e,f);
}

void _d(int u,int del){

    for(int e:v[u]){
        if(son[u] == e) continue;
        _d(e,1);
    }
    if(son[u]) _d(son[u],0);
    add(u);
    for(int e:v[u]){
        if(e == son[u]) continue;
        cal(e,1);
    }
    res[u] = ans;
    if(del) cal(u,0);
}


int main(){
    read(n);
    for(int i=2;i<=n;i++){
        int x;read(x);
        v[x].push_back(i);
    }
    dfs(1);
    _d(1,0);
    for(int i=1;i<=n;i++) printf("%lld\n",res[i]);
    return 0;
}
/***
***/