51nod1297 管理二叉树
第1行:1个数N。(1 <= N <= 100000) 第2 - N + 1行:每行1个数,对应排列的元素。(1 <= ai <= N)
输出共N行,每行1个数,对应添加当前元素后,每对节点之间的距离之和。
8 4 7 3 1 8 2 6 5
0 1 4 10 20 35 52 76
树 规律题 动态点分治
直接模拟建树妥妥被卡。
分析一波可以发现,将一个点x添加进树的时候,在所有已有点中找到x的前驱和后继,x要么是前驱的右儿子,要么是前驱的左儿子。
思考一下或者手玩一波会发现“前驱的右儿子”和“后继的左儿子“不会同时为空,所以要添加到哪里是确定的。
我们可以离线操作,先将树建好,之后按顺序每次添加一个点,统计它到所有已有点的距离。
剩下的部分显然是动态点分治模板题。
写完WA了一半点,旁边czy说:“想必没有开LL”
开了LL以后还有三个点WA,旁边czy说:“想必数组不够大”
开大了数组就AC辣
他真是个小天才!
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<set> 7 #define LL long long 8 using namespace std; 9 const int INF=0x3f3f3f3f; 10 const int mxn=150010; 11 int read(){ 12 int x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 struct edge{ 18 int v,nxt; 19 }e[mxn<<1]; 20 int hd[mxn],mct=0; 21 void add_edge(int u,int v){ 22 e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return; 23 } 24 void insert(int u,int v){ 25 add_edge(u,v);add_edge(v,u);return; 26 } 27 int sz[mxn],mc[mxn],rot,smm; 28 int dep[mxn],dis[mxn][23]; 29 int an[mxn][23]; 30 LL ans1[mxn],ans2[mxn],num[mxn]; 31 LL nowans; 32 bool vis[mxn]; 33 void DFS_sz(int u,int fa){ 34 sz[u]=mc[u]=1; 35 for(int i=hd[u];i;i=e[i].nxt){ 36 int v=e[i].v;;if(v==fa || vis[v])continue; 37 DFS_sz(v,u); 38 sz[u]+=sz[v]; 39 mc[u]=(sz[v]>mc[u])?sz[v]:mc[u]; 40 } 41 mc[u]=max(mc[u],smm-sz[u]); 42 if(mc[u]<mc[rot])rot=u; 43 return; 44 } 45 void calc(int u,int fa,int ance,int dist){ 46 an[u][++dep[u]]=ance; 47 dis[u][dep[u]]=dist; 48 for(int i=hd[u];i;i=e[i].nxt){ 49 int v=e[i].v; 50 if(v==fa || vis[v])continue; 51 calc(v,u,ance,dist+1); 52 } 53 return; 54 } 55 void solve(int x){ 56 vis[x]=1; 57 // printf("solve:%d\n",x); 58 calc(x,x,x,0);dep[x]--; 59 for(int i=hd[x];i;i=e[i].nxt){ 60 int v=e[i].v; 61 if(!vis[v]){ 62 smm=sz[v]; mc[rot=0]=INF; 63 DFS_sz(v,x); 64 solve(rot); 65 } 66 } 67 return; 68 } 69 void add(int u){ 70 LL tmp=ans1[u]; 71 for(int i=dep[u];i>1;i--){ 72 LL dist=dis[u][i-1]; 73 tmp+=ans1[an[u][i-1]]-ans2[an[u][i]]; 74 tmp+=dist*(num[an[u][i-1]]-num[an[u][i]]); 75 } 76 nowans+=tmp; 77 num[u]+=1; 78 for(int i=dep[u];i>1;i--){ 79 LL dist=dis[u][i-1]; 80 ans1[an[u][i-1]]+=dist*1; 81 ans2[an[u][i]]+=dist*1; 82 num[an[u][i-1]]+=1; 83 } 84 return; 85 } 86 // 87 int ch[mxn][2]; 88 //int st[mxn],top=0; 89 int n,x[mxn],M[mxn],U[mxn]; 90 set<int>st; 91 void init(){ 92 st.insert(x[1]);set<int>::iterator it,it2; 93 for(int i=2;i<=n;i++){ 94 st.insert(x[i]); 95 it=it2=st.lower_bound(x[i]); 96 if(it!=st.end()){it++;if(it!=st.end())U[i]=(*it);} 97 if(it2!=st.begin()){it2--; M[i]=(*it2);} 98 } 99 for(int i=2;i<=n;i++){ 100 if(!M[i] || ch[M[i]][1]){ 101 ch[U[i]][0]=x[i]; 102 insert(U[i],x[i]); 103 continue; 104 } 105 if(!U[i] || ch[U[i]][0]){ 106 ch[M[i]][1]=x[i]; 107 insert(M[i],x[i]); 108 } 109 } 110 return; 111 } 112 int main(){ 113 int i,j; 114 n=read(); 115 for(i=1;i<=n;i++)x[i]=read(); 116 init(); 117 smm=n; 118 mc[rot=0]=INF; 119 DFS_sz(1,0); 120 solve(rot); 121 for(i=1;i<=n;i++){ 122 an[i][++dep[i]]=i; 123 dis[i][dep[i]]=0; 124 } 125 for(i=1;i<=n;i++){ 126 add(x[i]); 127 printf("%lld\n",nowans); 128 } 129 return 0; 130 }
转载于:https://www.cnblogs.com/SilverNebula/p/7095498.html
51nod1297 管理二叉树相关推荐
- 数据结构-----二叉树,树,森林之间的转换
图片和转换步骤来自这里 本文主要描述具体实现 用一种略微老土的话描述: 二叉树:每一节点最多有2个子节点,左边的叫左节点,右边的叫右节点,自己叫根节点. 树:每个节点的子节点数量不受限制. 森林:由若 ...
- 树的基本概念和遍历规则 数据结构和算法 二叉树遍历(前序、中序、后序、层次、深度优先、广度优先遍历)
zsychanpin 博客园 首页 新随笔 联系 订阅 管理 树的基本概念和遍历规则 树的递归定义 树是n(n>0)个结点的有限集,这个集合满足下面条件: ⑴有且仅有一个结点没有前驱 ...
- python中怎么统计英文字符的个数_【Python练习1】统计一串字符中英文字母、空格、数字和其他字符的个数...
练习思路: 1.输入一串字符 2.筛选出字符中的英文字母并统计 3.筛选出字符中的空格并统计 4.筛选出字符中的数字并统计 5.筛选出字符中的其他字符并统计 代码实现: def msg(s): abc ...
- bartender一行打印两个二次开发_C++ 智能指针和二叉树:图解层序遍历和逐层打印二叉树...
作者:apocelipes 链接:https://www.cnblogs.com/apocelipes/p/10758692.html 二叉树是极为常见的数据结构,关于如何遍历其中元素的文章更是数不 ...
- .net内存管理与指针
本人前段时间准备做个TIN三角网的程序,思想是是分割合并法,分割的同时建立平衡二叉树,然后子树建三角网并相互合并,再向上加入父亲的点集.由于我对.net语言熟点,就准备用c#语言实现.但是不知从那听过 ...
- 关于二叉树的几个必须掌握的实现
The best way to end your fear is to face it yourself. 结束恐惧的最佳办法就是自己面对. 本分分享了二叉搜索树的几种实现,由简入繁.说句题外话,马 ...
- BSP场景管理方法简介
BSP(Binary Space Partition,二叉空间分割)方法,在大型3d游戏场景管理方面,可以认为是已经证明了的,最成熟的,最经得起考验的场景管理方法.诸如虚幻系列引擎(Unreal 1, ...
- 二叉链表和职工管理系统结合_基于二叉链表的二叉树实现
main.c// 数据结构实验三 Created by 南隹 on 2019/11/12.// Copyright © 2019 南隹. All rights reserved.//以下代码部分功能需 ...
- sdh管理单元指针_C语言学习|指针的介绍
指针是C语言提供的一种特殊而又有非常重要的数据类型. 联合使用指针和结构体这两种数据类型可以有效地表示许多复杂的数据结构,如队列.堆栈.链表.树.图等. 指针这个内容为什么那么的重要? 1.指针为函数 ...
最新文章
- 使用alterMIME实现添加message footer功能
- CENTOS在输入ifconfig命令时,提示没有命令的处理方法
- springboot整个缓存_SpringBoot中整合Redis(缓存篇)
- 多线程与高并发(五):强软弱虚四种引用以及ThreadLocal的原理与源码
- python二分法查找程序_Python程序查找最大EVEN数
- java8新特性以及原因_JAVA8 十大新特性详解
- Batch批量替换hosts
- 资产模型数据初始化时应注意的事项
- 开关电源雷击浪涌整改_高频开关电源的EMC电磁兼容整改问题分析
- 汇编的接触——基础知识
- Hibernate相关内容
- 记账系统推荐金蝶精斗云_金蝶精斗云的免费财务做账软件有哪些?
- c#中使用BackgroundWorker
- 启动计算机管理服务,win10系统打开服务管理器的五种方法
- Python手游辅助教程之战双帕弥什脚本教程
- 计算机病毒模块测试题,计算机病毒分类测试题集
- Google SketchUp SDK
- L1-009 N个数求和---题解
- PHP Imagick发光文字
- 黑盒测试方法-----状态转换图
热门文章
- VSFLEXgrid控件几个特殊的属性方法的使用
- AndroidStudio_安卓原生开发_android10中android11中_bitmap缩放大小不一致_解决方案---Android原生开发工作笔记154
- JAVA高并发工作笔记0001---高并发编程之ConcurrentLinkedDeque
- 数据库工作笔记008---pg_hba.conf entry for host “192.168.2.111”, user “gpadmin”, database “template1”, SSL
- SpringCloud工作笔记031---Idea中JDK为1.8,还提示Diamond types are not supported at this language level
- sphereface conv64
- kafka集群安装部署
- pclint 与vs2010结合识别预处理器定义
- shell读取mysql_shell读取mysql数据库
- 随想录(软件中的bug)