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. Handler+Looper+MessageQueue深入详解

    概述:Android中的异步处理机制由四部分组成:Handler+Looper+MessageQueue+message,用于实现线程间的通信. 用到的概念: Handler: 主要作用是发送消息和处 ...

  2. SpringBoot学习(六)—— springboot快速整合RabbitMQ

    目录 Rabbit MQ消息队列 简介 Rabbit MQ工作模式 交换机模式 引入RabbitMQ队列 代码实战 Rabbit MQ消息队列 @ 简介 优点 erlang开发,并发能力强. 社区活跃 ...

  3. Linux下用Docker部署接口安全的运行环境

    背景:MySQL数据库运行在宿主机上(Linux) 需求:Redis.服务.页面分别运行在独立的docker中,并处于同一网络,容器内部重要目录要挂载在物理目录,保证数据安全 方法: 一.设置网络环境 ...

  4. vue下谷歌浏览器的扩展程序(vue-devtools-master)

    1,在百度网盘中下载压缩包,网盘地址:https://pan.baidu.com/s/1BnwWHANHNyJzG3Krpy7S8A ,密码:xm6s 2,将压缩包解压到F盘,F:\chromeVue ...

  5. 最小化安装CentOS 7 系统

    目录 CentOS 程序准备 开始安装系统 创建虚拟机 安装系统 CentOS 运维最常接触的系统就是CentOS系统,无论是版本 6 还是版本 7 而且在安装系统时,讲究最小化安装系统,之后当需要什 ...

  6. JS使用readAsDataURL读取图像文件

    JS使用readAsDataURL读取图像文件 FileReader对象的readAsDataURL方法可以将读取到的文件编码成Data URL.Data URL是一项特殊的技术,可以将资料(例如图片 ...

  7. day28

    断点调试 在想要加断点的地方用鼠标点击一下,你会看到一个红色圆圈 变红的地方,程序执行到,就会暂停 断点应该加在报错之前 绿色箭头表示快速跳到下一个断点执行 控制台报错,点击你能看懂的最后一行,光标会 ...

  8. hybrid app初体验,和react-native一起飞

    第一次启动了react-native的示例,今天主要把其中遇到的坑与解决的办法分享给大家.如有疏漏.错误还望指正. 首先还是要从hybrid app这个概念说起(如果对于这个过程不感兴趣的同学,可以直 ...

  9. 震惊!线上四台机器同一时间全部 OOM,到底发生了什么?

    案发现场 昨天晚上突然短信收到 APM (即 Application Performance Management 的简称),我们内部自己搭建了这样一套系统来对应用的性能.可靠性进行线上的监控和预警的 ...

  10. luogu P1972 [SDOI2009]HH的项链 |树状数组 或 莫队

    题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长. ...