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;
}
全部评论

相关推荐

白火同学:能。我当初应届沟通了1200,收简历50,面试10左右吧,加油投吧
投了多少份简历才上岸
点赞 评论 收藏
分享
Rena1ssanc...:对的,要是面评没太烂,勤更新简历等捞就行了,腾讯可以无限复活
点赞 评论 收藏
分享
昨天 11:02
中山大学 C++
字节刚oc,但距离九月秋招很近了有两段互联网实习,非腾讯字节。不敢赌转正,现在在纠结去还是不去如果实习俩月离职会有什么后果吗
阿城我会做到的:不去后悔一辈子,能否转正取决于ld的态度,只要他不卡,答辩就是走流程,个人觉得可以冲一把
投递字节跳动等公司9个岗位
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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