POJ2182题解——线段树

2019-12-20

by juruoOIer

1.线段树简介(来源:百度百科)

线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,实际应用时一般还要开4N的数组以免越界,因此有时需要离散化让空间压缩。
 
2.线段树实际应用
上面的都是些基本的线段树结构,但只有这些并不能做什么,就好比一个程序有输入没输出,根本没有任何用处。
 
最简单的应用就是记录线段是否被覆盖,随时查询当前被覆盖线段的总长度。那么此时可以在结点结构中加入一个变量int count;代表当前结点代表的子树中被覆盖的线段长度和。这样就要在插入(删除)当中维护这个count值,于是当前的覆盖总值就是根节点的count值了。
 
另外也可以将count换成bool cover;支持查找一个结点或线段是否被覆盖。
 
实际上,通过在结点上记录不同的数据,线段树还可以完成很多不同的任务。例如,如果每次插入操作是在一条线段上每个位置均加k,而查询操作是计算一条线段上的总和,那么在结点上需要记录的值为sum。
 
这里会遇到一个问题:为了使所有sum值都保持正确,每一次插入操作可能要更新O(N)个sum值,从而使时间复杂度退化为O(N)。
 
解决方案是Lazy思想:对整个结点进行的操作,先在结点上做标记,而并非真正执行,直到根据查询操作的需要分成两部分。
 
根据Lazy思想,我们可以在不代表原线段的结点上增加一个值toadd,即为对这个结点,留待以后执行的插入操作k值的总和。对整个结点插入时,只更新sum和toadd值而不向下进行,这样时间复杂度可证明为O(logN)。
 
对一个toadd值为0的结点整个进行查询时,直接返回存储在其中的sum值;而若对toadd不为0的一部分进行查询,则要更新其左右子结点的sum值,然后把toadd值传递下去,再对这个查询本身,左右子结点分别递归下去。时间复杂度也是O(nlogN)。
 
3.代码实现
下面先给出线段树建树的代码:
void build_tree(int l,int r,int k)
{
tree[k].l=l;
tree[k].r=r;
tree[k].sum=r-l+;
if(l==r) return ;
int m=(l+r)>>;
build_tree(l,m,k<<);
build_tree(m+,r,(k<<)|);
}

这里使用结构体来完成二叉树的操作:

struct Tree
{
int l,r,sum;
}tree[*N];

最后,给出POJ2182的代码,用以讲解线段树:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=;
int ans[N],b[N];
int n;
struct Tree
{
int l,r,sum;
}tree[*N];
void build_tree(int l,int r,int k)
{
tree[k].l=l;
tree[k].r=r;
tree[k].sum=r-l+;
if(l==r) return ;
int m=(l+r)>>;
build_tree(l,m,k<<);
build_tree(m+,r,(k<<)|);
}
void solve(int num,int k,int i)
{
tree[k].sum--;
if(tree[k].l==tree[k].r)
{
ans[i]=tree[k].l;
return ;
}
if(num<=tree[*k].sum) solve(num,*k,i);
else solve(num-tree[*k].sum,*k+,i);
}
int main()
{
int i,j;
scanf("%d",&n);
for(i=;i<=n;i++) scanf("%d",&b[i]);
b[]=;
build_tree(,n,);
for(i=n;i>=;i--) solve(b[i]+,,i);
for(i=;i<=n;i++) printf("%d\n",ans[i]);
}

部分知识来源:百度百科

POJ2182题解——线段树的更多相关文章

  1. poj2182(线段树求序列第k小)

    题目链接:https://vjudge.net/problem/POJ-2182 题意:有n头牛,从1..n编号,乱序排成一列,给出第2..n个牛其前面有多少比它编号小的个数,记为a[i],求该序列的 ...

  2. luoguP5105 不强制在线的动态快速排序 [官方?]题解 线段树 / set

    不强制在线的动态快速排序 题解 算法一 按照题意模拟 维护一个数组,每次直接往数组后面依次添加\([l, r]\) 每次查询时,暴力地\(sort\)查询即可 复杂度\(O(10^9 * q)\),期 ...

  3. 理想乡题解 (线段树优化dp)

    题面 思路概述 首先,不难想到本题可以用动态规划来解,这里就省略是如何想到动态规划的了. 转移方程 f[i]=min(f[j]+1)(max(i-m,0)<=j<i 且j符合士兵限定) 注 ...

  4. POJ 3468 A Simple Problem with Integers(详细题解) 线段树

    这是个线段树题目,做之前必须要有些线段树基础才行不然你是很难理解的. 此题的难点就是在于你加的数要怎么加,加入你一直加到叶子节点的话,复杂度势必会很高的 具体思路 在增加时,如果要加的区间正好覆盖一个 ...

  5. [bzoj2752]高速公路 题解(线段树)

    2752: [HAOI2012]高速公路(road) Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2102  Solved: 887[Submit] ...

  6. codedecision P1113 同颜色询问 题解 线段树动态开点

    题目描述:https://www.cnblogs.com/problems/p/11789930.html 题目链接:http://codedecision.com/problem/1113 这道题目 ...

  7. codedecision P1112 区间连续段 题解 线段树

    题目描述:https://www.cnblogs.com/problems/p/P1112.html 题目链接:http://codedecision.com/problem/1112 线段树区间操作 ...

  8. 【poj2828】Buy Tickets 线段树 插队问题

    [poj2828]Buy Tickets Description Railway tickets were difficult to buy around the Lunar New Year in ...

  9. Codeforces Round #254 (Div. 1) C. DZY Loves Colors 线段树

    题目链接: http://codeforces.com/problemset/problem/444/C J. DZY Loves Colors time limit per test:2 secon ...

随机推荐

  1. 携程Apollo简单入门教程这一篇就够了

    1. Apollo背景 对程序配置的期望值也越来越高:配置修改后实时生效,灰度发布,分环境.分集群管理配置,完善的权限.审核机制……   废话不多说,参考官方文档   如果不想看文档, 也没关系, 跟 ...

  2. 20190926-2 选题 Scrum立会报告+燃尽图05

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/8678 一.小组情况组长:迟俊文组员:宋晓丽 梁梦瑶 韩昊 刘信鹏队名:扛 ...

  3. DDCTF2019 的四道题wp

    MIsc:流量分析 这道题,在比赛的时候就差个key了,但是没想到要改高度,后来群里师傅说了下,就再试试, 导出来改高度. 导出来,把 把%5c(4)前面的hex删掉,改成png,就直接拿去那个img ...

  4. Theano中的导数

    计算梯度 现在让我们使用Theano来完成一个稍微复杂的任务:创建一个函数,该函数计算相对于其参数x的某个表达式y的导数.为此,我们将使用宏T.grad.例如,我们可以计算相对于的梯度 import ...

  5. Lua和C交互的简易教程

    转载请标明出处:http://blog.csdn.net/shensky711/article/details/52458051 本文出自: [HansChen的博客] Lua栈 要理解Lua和C++ ...

  6. java多线程的wait、notify/notifyAll区别

    1.wait().notify/notifyAll() 方法是Object的本地final方法,无法被重写.   2.wait()使当前线程阻塞,前提是 必须先获得锁,一般配合synchronized ...

  7. Centos 7 启动 Tomcat 7、8 慢的问题

    查看原因 首先查看日志信息,查看因为什么而启动慢 在CentOS7启动Tomcat时,启动过程很慢,需要几分钟,经过查看日志,发现耗时在这里:是session引起的随机数问题导致的.Tocmat的Se ...

  8. Linux海量数据高并发实时同步架构方案杂谈

    不论是Redhat还是CentOS系统,除去从CDN缓存或者数据库优化.动静分离等方面来说,在架构层面上,实 现海量数据高并发实时同步访问概括起来大概可以从以下几个方面去入手,当然NFS的存储也可以是 ...

  9. Haproxy安装部署文档及多配置文件管理方案

    一.部署安装 二.软件配置 三.系统服务 四.日志配置 五.小结 文章目录 最近我在负责一个统一接入层的建设项目,涉及到 Haproxy 和 ospf 的运维部署,本文分享一下我在部署 Haproxy ...

  10. js如何衔接css3的多个@keyframes动画?

    css3特效动画,我们在编写页面中经常遇到,而且是在同一个div模块上有多个衔接的不同动画,css中,我们经常使用animation-delay (规定在动画开始之前的延迟)进行处理. 那么,下面分享 ...