[51nod1297]管理二叉树
Input
第1行:1个数N。(1 <= N <= 100000)
第2 - N + 1行:每行1个数,对应排列的元素。(1 <= ai <= N)
Output
输出共N行,每行1个数,对应添加当前元素后,每对节点之间的距离之和。
先把树求出来。。具体的话就是每次添加元素之后,找到这个数的前驱后继,哪个有空位这个元素就在哪。随便写个什么数据结构。
求节点的距离和的话。。我写了点分治,每次查找完往里面加点...查找啊去重啊什么的都是一样的套路...
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstdlib>
#include<bitset>
//#include<ctime>
#define ll long long
#define ull unsigned long long
#define ui unsigned int
#define d double
//#define ld long double
using namespace std;
const int maxn=,mxnode=maxn;
struct zs{int too,pre;}e[maxn<<];int tot,last[maxn];
int lc[mxnode],rc[mxnode],v[mxnode],rnd[mxnode],tt;int V,PRE,AFT,rt;bool u[maxn][];
int sz[maxn],mx[maxn],RT,POI,dis[maxn],st[maxn],top,mxdep[maxn];bool del[maxn];
int bel[maxn][],belson[maxn<<][],dist[maxn][],_sz[maxn],_sonsz[maxn<<];int ID;
ll _sum[maxn],_sonsum[maxn<<];
int a[maxn];
int i,j,k,n,m; int ra,fh;char rx;
inline int read(){
rx=getchar(),ra=,fh=;
while((rx<''||rx>'')&&rx!='-')rx=getchar();
if(rx=='-')fh=-,rx=getchar();
while(rx>=''&&rx<='')ra=ra*+rx-,rx=getchar();return ra*fh;
}
inline void maxs(int &a,int b){if(b>a)a=b;}
inline void lturn(int &x){int R=rc[x];rc[x]=lc[R],lc[R]=x,x=R;}
inline void rturn(int &x){int L=lc[x];lc[x]=rc[L],rc[L]=x,x=L;}
inline void insert(int &x){
if(!x){x=++tt,v[x]=V,rnd[x]=rand();return;}
if(V<v[x]){
insert(lc[x]);
if(rnd[lc[x]]<rnd[x])rturn(x);
}else{
insert(rc[x]);
if(rnd[rc[x]]<rnd[x])lturn(x);
}
}
void getpre(int x){
if(!x)return;
if(v[x]<V)PRE=v[x],getpre(rc[x]);else getpre(lc[x]);
}
void getaft(int x){
if(!x)return;
if(v[x]>V)AFT=v[x],getaft(lc[x]);else getaft(rc[x]);
}
inline void ins(int a,int b){
e[++tot].too=b,e[tot].pre=last[a],last[a]=tot;
e[++tot].too=a,e[tot].pre=last[b],last[b]=tot;
} void getrt(int x,int fa){
sz[x]=,mx[x]=;
for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa&&!del[e[i].too])
getrt(e[i].too,x),maxs(mx[x],sz[e[i].too]),sz[x]+=sz[e[i].too];
maxs(mx[x],POI-sz[x]);
if(mx[x]<mx[RT])RT=x;
}
void getpoi(int x,int fa){
dis[x]=dis[fa]+,st[++top]=x,sz[x]=;
for(int i=last[x];i;i=e[i].pre)if(e[i].too!=fa&&!del[e[i].too])
getpoi(e[i].too,x),sz[x]+=sz[e[i].too];
}
void work(int x,int dep){
int i,p;
RT=,getrt(x,),x=RT,mxdep[x]=dep,bel[x][dep]=x,dist[x][dep]=dis[x]=;
for(i=last[x];i;i=e[i].pre)if(!del[e[i].too]){
getpoi(e[i].too,x);ID++;
while(top)p=st[top--],bel[p][dep]=x,belson[p][dep]=ID,dist[p][dep]=dis[p];
}
del[x]=,sz[x]=-;
for(i=last[x];i;i=e[i].pre)if(!del[e[i].too])
POI=sz[e[i].too],work(e[i].too,dep+);
} int main(){
n=read();
for(i=;i<=n;i++){
a[i]=read();
if(i>){
PRE=AFT=,V=a[i],getpre(rt),getaft(rt),
insert(rt);
if(!PRE||!AFT)ins(PRE|AFT,a[i]),u[PRE|AFT][PRE>]=;
else if(!u[PRE][])u[PRE][]=,ins(PRE,a[i]);
else u[AFT][]=,ins(AFT,a[i]);
}else V=a[i],insert(rt);
}
// for(i=1;i<=n;i++)for(j=last[i];j;j=e[j].pre)printf("%d-->%d\n",i,e[j].too); mx[]=<<,POI=n,work(a[],);ll ans=;int fa,son,dis;
for(i=;i<=n;i++){
k=a[i]; ans+=_sum[k],_sz[k]++;
for(j=mxdep[k]-;j;j--)
fa=bel[k][j],son=belson[k][j],dis=dist[k][j],
ans+=1ll*dis*(_sz[fa]-_sonsz[son])+_sum[fa]-_sonsum[son],
_sz[fa]++,_sonsz[son]++,_sum[fa]+=dis,_sonsum[son]+=dis; printf("%lld\n",ans);
}
}
[51nod1297]管理二叉树的更多相关文章
- 51nod 1297 管理二叉树
一个初始为空的二叉搜索树T,以及1到N的一个排列P: {a1, a2, ..., aN}.我们向这个二叉搜索树T添加这些数,从a1开始, 接下来是 a2, ..., 以aN结束.在每一个添加操作后,输 ...
- 51 nod 1297 管理二叉树
原题链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1297 先是暴力加优化T了最后两个点…… 我还是来想想正解吧. ...
- 四则运算(Java) 陈志海 邓宇
目录 Github项目地址 PSP表格 功能要求 题目 功能(已全部实现) 效能分析 设计实现过程 数值生成 算式生成 问题集生成 设计实现过程 代码说明 测试运行 代码覆盖率 项目小结 Github ...
- Netty源码解析 -- PoolChunk实现原理(jemalloc 3的算法)
前面文章已经分享了Netty如何实现jemalloc 4算法管理内存. 本文主要分享Netty 4.1.52之前版本中,PoolChunk如何使用jemalloc 3算法管理内存. 感兴趣的同学可以对 ...
- 深入C#内存管理来分析值类型&引用类型,装箱&拆箱,堆栈几个概念组合之间的区别
C#初学者经常被问的几道辨析题,值类型与引用类型,装箱与拆箱,堆栈,这几个概念组合之间区别,看完此篇应该可以解惑. 俗话说,用思想编程的是文艺程序猿,用经验编程的是普通程序猿,用复制粘贴编程的是2B程 ...
- C语言实现二叉树-02版
---恢复内容开始--- 昨天,提交完我们的二叉树项目后,今天早上项目经理早早给我打电话: 他说,小伙子干的不错.但是为什么你上面的insert是recusive的呢? 你难道不知道万一数据量大啦!那 ...
- C++11 智能指针unique_ptr使用 -- 以排序二叉树为例
用智能指针可以简化内存管理.以树为例,如果用普通指针,通常是在插入新节点时用new,在析构函数中调用delete:但有了unique_ptr类型的智能指针,就不需要在析构函数中delete了,因为当u ...
- linux内核分析之内存管理
1.struct page /* Each physical page in the system has a struct page associated with * it to keep tra ...
- Android 内存管理(二)
很多开发者都是从j2me或j2ee上过来的,对于内存的使用和理解并不是很到位,Android开发网本次给大家一些架构上的指导,防止出现豆腐渣工 程的出现.Android作为以Java语言为主的智能平台 ...
随机推荐
- [array] leetcode - 31. Next Permutation - Medium
leetcode - 31. Next Permutation - Medium descrition Implement next permutation, which rearranges num ...
- lua 实现tableToString
function tableToString(studentNum) local str = "{ " str = str.."\n" for k, v in ...
- 树形dp系列
1.火车站开饭店 最大独立集裸题 #include<iostream> #include<cstdio> #include<cstdlib> #include< ...
- bzoj 2302: [HAOI2011]Problem c
Description 给n个人安排座位,先给每个人一个1~n的编号,设第i个人的编号为ai(不同人的编号可以相同),接着从第一个人开始,大家依次入座,第i个人来了以后尝试坐到ai,如果ai被占据了, ...
- Linux内置命令
主要Shell内置命令 Shell有很多内置在其源代码中的命令.这些命令是内置的,所以Shell不必到磁盘上搜索它们,执行速度因此加快.不同的Shell内置命令有所不同. A.2.1 bash内置命令 ...
- 2017双11海量数据下EagleEye的使命和挑战
摘要: EagleEye作为阿里集团老牌的链路跟踪系统,其自身业务虽不在交易链路上,但却监控着全集团的链路状态,特别是在中间件的远程调用上,覆盖了集团绝大部分的场景,在问题排查和定位上发挥着巨大的作用 ...
- Nodejs密集型CPU解决方案
首先说一下nodejs单线程的优势: 高性能,与php相比,避免了频繁创建切换线程的开销,执行更加迅速,资源占用小. 线程安全,不用担心同一变量被多线程读写,造成程序崩溃. 单线程的异步和非阻塞,其实 ...
- Linux下jira自启动设置
jira 的启动主要依靠的是bin目录下的catalina.sh脚本,提供了如init脚本的start,stop等参数----------------------------------------- ...
- 活动倒计时-兼容ios
最近要做一个活动,需要用倒计时,写好之后再IOS上无效,经过百度知道了,原来IOS不能识别格式"2017-11-09 --",所以要进行转换才有效 直接上代码了: <!DOC ...
- 一、 kettle开发、上线常见问题以及防错规范步骤
此篇说明对应的kettle版本是6.1,实际使用时7.x应该也是一样的. 一. kettle开发流程(规范步骤,防止出错) (一) Kettle设置检查 资源库连接 如果不加一下配置 ...