luogu1377 树的序 (线段树)
2024-10-11 01:18:08
题意:给你一个1~N的排列,然后让你按顺序把它们插到一个二叉搜索树里,然后问能插出同样的二叉搜索树的 字典序最小的排列是什么
本来可以直接模拟建树然后dfs一下输出结果...然而有可能会退化成链,最差复杂度是O($n^2$)
然后貌似这题可以用笛卡尔树,先对输入排序然后实现O(n)建树..但我不会
考虑线段树做法,按照权值建线段树,维护区间中最小的序号
那我从根节点开始做(输入和输出的第一个数一定相同),每次找它左子树对应的权值区间范围中最小的序号,就是左子树的根;右子树同理
这样一直做下来,每做到一个数直接输出即可
复杂度是O(nlogn)
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int maxn=; int mi[maxn*],val[maxn],N; void insert(int p,int l,int r,int x,int y){
if(l==r) mi[p]=y;
else{
int m=l+r>>;
if(x<=m) insert(p<<,l,m,x,y);
else insert(p<<|,m+,r,x,y);
mi[p]=min(mi[p<<],mi[p<<|]);
}
}
int query(int p,int l,int r,int x,int y){
if(x<=l&&r<=y) return mi[p];
else{
int m=l+r>>;int re=0x3f3f3f3f;
if(x<=m) re=min(query(p<<,l,m,x,y),re);
if(y>m) re=min(query(p<<|,m+,r,x,y),re);
return re;
}
} void solve(int x,int l,int r){
if(x) printf("%d ",x);
if(x>l+) solve(val[query(,,N,l+,x-)],l,x);
if(x<r-) solve(val[query(,,N,x+,r-)],x,r);
} int main(){
int i,j,k,p,root;
scanf("%d",&N);
memset(mi,,sizeof(mi));
for(i=;i<=N;i++){
scanf("%d",&j);val[i]=j;
insert(,,N,j,i);
}solve(,,N+); }
最新文章
- OJ-Triangle
- 控件(进度类): RangeBase, Slider, ProgressBar, ProgressRing
- CentOS命令登录MySQL时,报错ERROR 1045 (28000):
- 简谈 JavaScript、Java 中链式方法调用大致实现原理
- 给定一数组,输出满足2a=b(a,b代表数组中的数)的数对,要求时间复杂度尽量低。
- EFI怎么装系统? UEFI BIOS
- 项目开发过程中什么是开发环境、测试环境、生产环境、UAT环境、仿真环境?
- vue 修饰符
- 深入margin
- drone 1.0 新功能试用以及说明
- 1.汇编指令介绍(arm)
- apk中添加第三方so文件
- Apache Jmeter 教程
- gcc自有的define语法,解决变量多次自加的问题
- day5-import机制详述
- 【转载】Leaflet 中文api
- Get MAC address using POSIX APIs
- this和target目标对象的区别
- 根据日期查询年龄js
- POJ 2559 Largest Rectangle in a Histogram(单调栈)
热门文章
- 【php增删改查实例】第十三节 - EasyUI列格式化
- zjoi2018 day1游记
- SDP服务搜索流程源码分析
- Gitlab备份和恢复操作记录
- 百度之星-day1-1003-度度熊剪纸条
- “北航学堂”M2阶段postmortem
- sixsix团队“餐站”应用代码规范及开发文档
- 《Linux内核分析》第八周学习小结 进程的切换和系统的一般执行过程
- 个人实验 github地址:https://github.com/quchengyu/cher
- JVM EXCEPTION_ACCESS_VIOLATION