Vijos-P1103题解【线段树】
本文为原创,转载请注明:http://www.cnblogs.com/kylewilson/
题目出处:
题目描述:
一条马路从数轴0到L,每个位置0,1,2,......,L都有一棵树,现需要将一些区间的树清除,区间可能有交集,求清除后还剩下多少棵树?
输入:
输入的第一行有两个整数:L(1 <= L <= 10000)和 M(1 <= M <= 100),L代表马路的长度,M代表区域的数目,L和M之间用一个空格隔开。接下来的M行每行包含两个不同的整数,用一个空格隔开,表示一个区域的起始点和终止点的坐标。
500 3
150 300
100 200
470 471
思路分析:
第一感觉,可以用数组a[10000]来模拟马路上的树,1表示有树,每次操作,则将对应区间所有点改为0,最终统计为1的点,但时间复杂度O(L*M),这明显不是最优的解法;
再仔细一想,每次都是对一个区间进行操作,而且对每一个点的操作都是相同的,所以考虑是否可以批量操作。
对于批量操作区间有线段树,树状树组等算法,本文讨论用线段树来解,树状树组算法以后会详细介绍。
那么问题来了,为什么会想到用线段树来解呢?即线段树能解决哪类问题?
线段树关键点:大区间的操作及结果等价于两个相邻的子区间操作及结果。
每次对马路上的树进行区间操作,如移除区间[a,b]上的树,也等价于移除区间[a,k],[k+1,b](a<=k<=b)上的树;
并且当区间上的树已经移除后,再重复移除也对最终结果无影响
如上图,树中每个节点表示一段区间
每个节点需要记录如下关键信息
left: 区间左起点
right: 区间右终点
count: 区间还剩下的树,初始为right-left+1;
1)更新树时,如果区间在需要操作的范围内,则将区间所有树清除,即count=0,直接返回,不需要再去清除所有子节点;
2)父节点同时更新count值,father.count=lson.count+right.count;
当父节点已经为0,则说明该区间已经全部被清除,此时左右子节点之和可能不等于0,看1)中并没有去清除子节点;
所以父节点还是保持0
最终剩下的树即为根节点中的树,即root.count。
C++源码如下:
github: https://github.com/Kyle-Wilson1/Vijos/tree/master/P1103
#include <iostream>
#include <fstream> using namespace std; struct SegmentTree {
int left, right, count;
SegmentTree *lson, *rson;
}; SegmentTree *buildTree(int l, int r) {
if (l > r) {
return nullptr;
}
if (l == r) {
auto *root = new SegmentTree{l, r, 1, nullptr, nullptr};
return root;
}
auto *root = new SegmentTree{l, r, r - l + 1, nullptr, nullptr};
int mid = (l + r) >> 1;
root->lson = buildTree(l, mid);
root->rson = buildTree(mid + 1, r);
return root;
} void removeRegion(SegmentTree *root, int regionLeft, int regionRight) {
if (root->left >= regionLeft && root->right <= regionRight) {
root->count = 0;
return;
}
if (root->right < regionLeft || root->left > regionRight) {
return;
}
removeRegion(root->lson, regionLeft, regionRight);
removeRegion(root->rson, regionLeft, regionRight);
root->count = min(root->count, root->lson->count + root->rson->count);
}
int main() { ifstream fin("a.in");
ofstream fout("a.out"); int l, m, i = 0, regionLeft, regionRight;
fin >> l >> m;
SegmentTree *root;
//build segment tree
root = buildTree(0, l); for (i = 0; i < m; i++) {
fin >> regionLeft >> regionRight;
removeRegion(root, regionLeft, regionRight);
} fout << root->count;
deleteMem(root);
fin.close();
fout.close();
return 0;
}
Vijos-P1103题解【线段树】的更多相关文章
- POJ2182题解——线段树
POJ2182题解——线段树 2019-12-20 by juruoOIer 1.线段树简介(来源:百度百科) 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线 ...
- luoguP5105 不强制在线的动态快速排序 [官方?]题解 线段树 / set
不强制在线的动态快速排序 题解 算法一 按照题意模拟 维护一个数组,每次直接往数组后面依次添加\([l, r]\) 每次查询时,暴力地\(sort\)查询即可 复杂度\(O(10^9 * q)\),期 ...
- 理想乡题解 (线段树优化dp)
题面 思路概述 首先,不难想到本题可以用动态规划来解,这里就省略是如何想到动态规划的了. 转移方程 f[i]=min(f[j]+1)(max(i-m,0)<=j<i 且j符合士兵限定) 注 ...
- POJ 3468 A Simple Problem with Integers(详细题解) 线段树
这是个线段树题目,做之前必须要有些线段树基础才行不然你是很难理解的. 此题的难点就是在于你加的数要怎么加,加入你一直加到叶子节点的话,复杂度势必会很高的 具体思路 在增加时,如果要加的区间正好覆盖一个 ...
- [bzoj2752]高速公路 题解(线段树)
2752: [HAOI2012]高速公路(road) Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2102 Solved: 887[Submit] ...
- codedecision P1113 同颜色询问 题解 线段树动态开点
题目描述:https://www.cnblogs.com/problems/p/11789930.html 题目链接:http://codedecision.com/problem/1113 这道题目 ...
- codedecision P1112 区间连续段 题解 线段树
题目描述:https://www.cnblogs.com/problems/p/P1112.html 题目链接:http://codedecision.com/problem/1112 线段树区间操作 ...
- 【poj2828】Buy Tickets 线段树 插队问题
[poj2828]Buy Tickets Description Railway tickets were difficult to buy around the Lunar New Year in ...
- 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 ...
- Poj 3468-A Simple Problem with Integers 线段树,树状数组
题目:http://poj.org/problem?id=3468 A Simple Problem with Integers Time Limit: 5000MS Memory Limit ...
随机推荐
- 揭开DRF序列化技术的神秘面纱
在RESTful API中,接口返回的是JSON,JSON的内容对应的是数据库中的数据,DRF是通过序列化(Serialization)的技术,把数据模型转换为JSON的,反之,叫做反序列化(dese ...
- 其它语言通过HiveServer2访问Hive
先解释一下几个名词: metadata :hive元数据,即hive定义的表名,字段名,类型,分区,用户这些数据.一般存储关系型书库mysql中,在测试阶段也可以用hive内置Derby数据库. me ...
- Jmeter二次开发——基于Java请求
简述 这近几年,越来越多非http的协议需要进行性能测试,包括不仅限于各类rpc.mq.缓存等.对于这些协议,市面上可能没有现成的工具可以直接使用,这个时候,我们可以自己动手,通过编写相应的JavaS ...
- windows jupyter lab中.ipynb转中文PDF
在jupyter lab中,File-Export Notebook as-Export Notebook to PDF,可以导出成PDF格式的文档,但在操作前需要安装些程序.1. 安装pandocA ...
- java_day 02
一.方法的传入参数可以为一个 类 类型 有往方法里传 int ,double ,char 类型的值的,第一次学习到居然还能往方法里传 类 定义好一个 Phone 类 实例化对象 ,并且往 method ...
- 干货满满:python实现二维图制作
python全代码如下 import re import csv import matplotlib.pyplot as plt x=[] y=[] m=eval(input()) #输入折线条数 f ...
- python 实现数值积分与画图
import numpy as np from scipy import integrate def half_circle(x): return (1 - x ** 2) ** 0.5 N = 10 ...
- python基本输入与输出
内置函数print()用于输出信息到标准控制台或指定文件,语法格式为: print(value1,value2,... , sep=' ', end='\n', file=sys.stdout, fl ...
- java中根据后端返回的数据加载table列表
<%//引入 js @ page language="java" pageEncoding="UTF-8"%> <!DOCTYPE HTML& ...
- MRP物料需求计划
1.重订货点的采购计划. 计算方式:再订货点的库存数量 = 安全库存 + 采购提前期 * 每天消耗的数量 一旦库存数量触及再订货点的库存数量,需触发采购订单订购物料,理想的情况下 ,下次到采购订单收货 ...