2020 CCPC-Wannafly Winter Camp Day2 (Div.1&2) E. 阔力梯的树

启发式合并即可

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
vector<int>v[N];
int n,sz[N];
void dfs(int now){
  sz[now]=1;
  for(auto k:v[now]){
    dfs(k);
    sz[now]+=sz[k];
  }
}
LL ans[N],MAX=1e18,MIN=-1e18;
int num[N];
set<LL>fu[N];
void merge(int x,int y){
  for(auto k:fu[y]){
    if(k==MAX||k==MIN)
      continue;
    auto ne=--fu[x].upper_bound(k);
    auto f=fu[x].upper_bound(k);
    if(*f==MAX){
      if(*ne!=MIN){
        ans[x]+=(k-*ne)*(k-*ne);
      }
    }else{
      if(*ne==MIN){
        ans[x]+=(*f-k)*(*f-k);
      }else{
        ans[x]-=(*f-*ne)*(*f-*ne);
        ans[x]+=(*f-k)*(*f-k);
        ans[x]+=(k-*ne)*(k-*ne);
      }
    }
    fu[x].insert(k);
  }
}
LL ok[N];
void gao(int now){
  fu[now].insert(now);
  for(auto k:v[now]){
    gao(k);
    int x=num[now];
    int y=num[k];
    if(fu[x].size()>=fu[y].size()){
      merge(x,y);
      fu[y].clear();
    }else{
      merge(y,x);
      fu[x].clear();
      swap(num[k],num[now]);
    }
  }
  ok[now]=ans[num[now]];
}
int main() {
  scanf("%d",&n);
  for(int i=1;i<=n;i++){
    num[i]=i;
    fu[i].insert(MAX);
    fu[i].insert(MIN);
  }
  for(int i=2;i<=n;i++){
    int x;
    scanf("%d",&x);
    v[x].pb(i);
  }
  dfs(1);
  gao(1);
  for(int i=1;i<=n;i++){
    printf("%lld\n",ok[i]);
  }
  return 0;
}
全部评论

相关推荐

找工作勤劳小蜜蜂:自我描述部分太差,完全看不出想从事什么行业什么岗位,也看不出想在哪个地区发展,这样 会让HR很犹豫,从而把你简历否决掉。现在企业都很注重员工稳定性和专注性,特别对于热爱本行业的员工。 你实习的工作又太传统的it开发(老旧),这部分公司已经趋于被淘汰,新兴的互联网服务业,比如物流,电商,新传媒,游戏开发和传统的It开发有天然区别。不是说传统It开发不行,而是就业岗位太少,基本趋于饱和,很多老骨头还能坚持,不需要新血液。 工作区域(比如长三角,珠三角,成渝)等也是HR考虑的因素之一,也是要你有个坚定的决心。否则去几天,人跑了,HR会被用人单位骂死。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务