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 ...
随机推荐
- 一文搞懂Java引用拷贝、浅拷贝、深拷贝
微信搜一搜 「bigsai」 专注于Java和数据结构与算法的铁铁 文章收录在github/bigsai-algorithm 在开发.刷题.面试中,我们可能会遇到将一个对象的属性赋值到另一个对象的情况 ...
- Kudu的特点
Kudu的特点 0.原理 列式存储管理器 一个列式存储数据的地方,跟mysql差不多,只是mysql是行式存储. 他是一个集群,能分布式存储. 查询也是写sql语句. 列式存储效率高. 1.为什么会有 ...
- python菜鸟教程学习:数据结构
列表方法 list.append(x):把一个元素添加到列表的结尾,相当于 a[len(a):] = [x]. list.extend(L):通过添加指定列表的所有元素来扩充列表,相当于 a[len( ...
- winform判断程序是否运行,且只能运行一个实例
前言 判断程序是否已经运行,使程序只能运行一个实例有很多方法,下面记录两种. 目前使用的是第一种方法. 方法1:线程互斥 static class Program { private static S ...
- 进入mysql数据库修改密码
mysql -hlocalhost -uroot -p #修改密码mysql> set password for root@localhost = password('root');#启动数据库 ...
- easyui中给table列表中加序号
$('#xyData_healthList').datagrid({ width: 'auto', height: 'auto', striped: true, fit: true, paginati ...
- 前端面试题归类-HTML1
一.HTML5的新特性? 1.增强了表单,input新增了一些type:常用 color----定义调色板 tel-----定义包含电话号码的输入域 email---定义包含email地址的输入域 s ...
- HTTP高级(Cookie,Session ,LocalStorage )
Cookie 服务器通过 Set-Cookie 头给客户端一串字符串 客户端每次访问相同域名的网页时,必须带上这段字符串 客户端要在一段时间内保存这个Cookie Cookie 默认在用户关闭页面后就 ...
- centosl7简洁版配置
生产环境安装了精简版的centos7需要进行相关配置,添加相关组件才能更好的使用! 由于不同的安装方式欠缺的组件不尽相同,本例尽可能满足一般的生产环境的需要!!! 一.安装ifconfig服务 在没有 ...
- github与svn的区别
github与svn都属于版本控件系统,但是两者不同于,github是分布式的,svn不是分布的是属于集中式的. 1) 最核心的区别Git是分布式的,而Svn不是分布的.能理解这点,上手会很容 ...