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;
}
/***
***/
京公网安备 11010502036488号