一个初始为空的二叉搜索树T,以及1到N的一个排列P: {a1, a2, ..., aN}。我们向这个二叉搜索树T添加这些数,从a1开始, 接下来是 a2, ..., 以aN结束。在每一个添加操作后,输出T上每对节点之间的距离之和。

例如:4 7 3 1 8 2 6 5。最终的二叉树为:
 
       4
     /   \
    3      7   
  /      /   \
 1      6     8
  \    /
   2  5
 
节点两两之间的距离和 = 6+5+5+4+3+2+1+5+4+4+3+2+1+4+3+3+2+1+3+2+2+1+2+1+1+2+1+3 = 76
Input
第1行:1个数N。(1 <= N <= 100000)
第2 - N + 1行:每行1个数,对应排列的元素。(1 <= ai <= N)
Output
输出共N行,每行1个数,对应添加当前元素后,每对节点之间的距离之和。

用set维护一下空的左右孩子位置和已插入的点可以O(nlogn)建树

然后就每加入 √(n) 个点重新树形dp一次,每加入一个点时和之前已加入但未dp的点间求距离,并计算和已dp的点对答案的贡献。
总复杂度O(n√(n)logn)

读入优化t了4个点,读入+输出优化t了1个点,fread+fwrite才a。。

#include<stdio.h>
#include<set>
#include<cmath>
const int N=;
char buf[],*ptr=buf,rbuf[],*rptr=rbuf-;
inline int _(){
int x=,c=*++rptr;
while(c<)c=*++rptr;
while(c>)x=x*+c-,c=*++rptr;
return x;
}
inline void _(long long x){
static int stk[],stp=;
if(!x)stk[stp++]=;
while(x)stk[stp++]=x%,x/=;
while(stp)*ptr++=stk[--stp]+;
*ptr++=;
}
int n,pv=;
std::set<int>le,re,in;
int ch[N][],xs[N],dep[N],fa[N],sz[N],pf[N],top[N];
long long F1[N],F2[N],ans=,ANS[N];
int _sz[N],h[N],tp[N];
inline int dis(int x,int y){
int a=top[x],b=top[y],s=dep[x]+dep[y];
while(a!=b){
if(dep[a]<dep[b])y=fa[b],b=top[y];
else x=fa[a],a=top[x];
}
s-=dep[dep[x]<dep[y]?x:y]<<;
return s;
}
void rebuild(){
ans=;
for(int i=pv-;~i;--i){
int w=xs[i],lc=ch[w][],rc=ch[w][];
h[w]=;
_sz[w]=+_sz[lc]+_sz[rc];
F1[w]=_sz[w]-+F1[lc]+F1[rc];
}
for(int i=;i<pv;++i){
int w=xs[i],lc=ch[w][],rc=ch[w][],s=_sz[rc]-_sz[lc];
F2[lc]=pv+s+F2[w]+F1[rc];
F2[rc]=pv-s+F2[w]+F1[lc];
F1[w]+=F2[w];
ans+=F1[w];
}
ans>>=;
}
int main(){
rbuf[fread(rbuf,,,stdin)]=;
n=_();
xs[]=_();
le.insert(xs[]);
re.insert(xs[]);
in.insert(xs[]);
for(int i=;i<n;++i){
int x=xs[i]=_();
in.insert(x);
auto it=le.upper_bound(x);
if(it!=le.end()){
auto it2=in.upper_bound(x);
if(it2!=in.end()&&*it2==*it){
ch[fa[x]=*it][]=x;
le.erase(it);
le.insert(x),re.insert(x);
continue;
}
}
it=re.upper_bound(x);
--it;
ch[fa[x]=*it][]=x;
re.erase(it);
le.insert(x),re.insert(x);
}
for(int i=;i<n;++i){
int w=xs[i];
dep[w]=dep[fa[w]]+;
}
for(int i=n-;~i;--i){
int w=xs[i];
int sl=sz[ch[w][]],sr=sz[ch[w][]];
sz[w]=+sl+sr;
pf[w]=ch[w][sl<sr];
}
for(int i=;i<n;i++){
int w=xs[i];
if(!top[w])for(int u=w;u;u=pf[u])top[u]=w;
}
int B=std::sqrt(n)/1.2+;
for(int i=;i<n;++i){
int w=xs[i],f=fa[w];
tp[w]=h[f]?tp[f]:f;
h[w]=h[f]+;
ans+=h[w]*pv+F1[tp[w]];
for(int j=pv;j<i;j++)ans+=dis(w,xs[j]);
ANS[i]=ans;
if(i%B==B-){
pv=i+;
rebuild();
}
}
for(int i=;i<n;++i)_(ANS[i]);
fwrite(buf,,ptr-buf,stdout);
return ;
}

51nod 1297 管理二叉树的更多相关文章

  1. 51 nod 1297 管理二叉树

    原题链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1297 先是暴力加优化T了最后两个点…… 我还是来想想正解吧. ...

  2. [51nod1297]管理二叉树

    一个初始为空的二叉搜索树T,以及1到N的一个排列P: {a1, a2, ..., aN}.我们向这个二叉搜索树T添加这些数,从a1开始, 接下来是 a2, ..., 以aN结束.在每一个添加操作后,输 ...

  3. 51nod 1297

    思路: 搞个栈模拟一下,也才5w; 直接wa1了..然后想到井口如果都进不去那就...一定GG了. 所以维护一下从井口到井底是非递增的就好了: #include <cstdio> #inc ...

  4. 四则运算(Java) 陈志海 邓宇

    目录 Github项目地址 PSP表格 功能要求 题目 功能(已全部实现) 效能分析 设计实现过程 数值生成 算式生成 问题集生成 设计实现过程 代码说明 测试运行 代码覆盖率 项目小结 Github ...

  5. Netty源码解析 -- PoolChunk实现原理(jemalloc 3的算法)

    前面文章已经分享了Netty如何实现jemalloc 4算法管理内存. 本文主要分享Netty 4.1.52之前版本中,PoolChunk如何使用jemalloc 3算法管理内存. 感兴趣的同学可以对 ...

  6. 51nod 1832 先序遍历与后序遍历【二叉树+高精度】

    题目链接:51nod 1832 先序遍历与后序遍历 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 对于给定的一个二叉树的先序遍历和后序遍历,输出有多少种满足条件的 ...

  7. 深入C#内存管理来分析值类型&引用类型,装箱&拆箱,堆栈几个概念组合之间的区别

    C#初学者经常被问的几道辨析题,值类型与引用类型,装箱与拆箱,堆栈,这几个概念组合之间区别,看完此篇应该可以解惑. 俗话说,用思想编程的是文艺程序猿,用经验编程的是普通程序猿,用复制粘贴编程的是2B程 ...

  8. C语言实现二叉树-02版

    ---恢复内容开始--- 昨天,提交完我们的二叉树项目后,今天早上项目经理早早给我打电话: 他说,小伙子干的不错.但是为什么你上面的insert是recusive的呢? 你难道不知道万一数据量大啦!那 ...

  9. C++11 智能指针unique_ptr使用 -- 以排序二叉树为例

    用智能指针可以简化内存管理.以树为例,如果用普通指针,通常是在插入新节点时用new,在析构函数中调用delete:但有了unique_ptr类型的智能指针,就不需要在析构函数中delete了,因为当u ...

随机推荐

  1. 二分查找(Binary Search)

    二分查找(Binary Search): int BinarySearch(int *array, int N, int key) { ; int left, right, mid; left = ; ...

  2. PE安装原版XP系统(含高版本PE安装选项灰色处理办法)

    PE 安装 XP 镜像流程准备原版 XP 安装光盘镜像放到硬盘非 C 盘. 可解压到本地经行安装, 也可以使用虚拟光驱载入安装 (本教程主要讲 PE 内虚拟光驱载入安装) 第一步:用 U 盘或硬盘/光 ...

  3. 如何让Visual Studio 清除最近打开项目 关闭上次未关闭的标签窗口

    删除最近打开的文件: 打开HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\9.0\FileMRUList 删除最近打开的项目: 打开HKEY_CUR ...

  4. [转载] Python 列表(list)、字典(dict)、字符串(string)常用基本操作小结

    创建列表 sample_list = ['a',1,('a','b')] Python 列表操作 sample_list = ['a','b',0,1,3] 得到列表中的某一个值 value_star ...

  5. ajax 城市区域选择三级联动

    <body onLoad="sheng()"><div class="xqbody">    <form action=" ...

  6. Codeforces Round #145 (Div. 2, ACM-ICPC Rules)

    A. Lefthanders and Righthanders \(i\)与\(i+\frac n2\)匹配,根据左右手调整位置. B. Reading 排序,取前\(k\)个. C. Weather ...

  7. Codeforces Round #138 (Div. 2)

    A. Parallelepiped 枚举其中一边,计算其他两条边. B. Array 模拟. C. Bracket Sequence 栈. D. Two Strings \(pre[i]\)表示第i个 ...

  8. 使用jquery插件实现图片延迟加载技术(懒加载)

    有时我们看到一些大型网站,页面如果有很多图片的时候,当你滚动到相应的行时,当前行的图片才即时加载的,这样子的话页面在打开只加可视区域的图片,而其它隐藏的图片则不加载,一定程序上加快了页面加载的速度,对 ...

  9. spring源码学习之【准备】cglib动态代理例子

    一:委托者 package com.yeepay.porxy.cglib.test; import java.util.HashMap; import java.util.Map; /** * 目标类 ...

  10. ps白平衡

    ps白平衡:在正常光线下看起来是白颜色的东西在有色光或者较暗的光线下看起来可能就不是白色,还有荧光灯下的"白"也是"非白".对于这一切如果能调整白平衡,则在所得 ...