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 ...
随机推荐
- vue第一单元(初识webpack-webpack的功能-webpack的初步使用)
第一单元(初识webpack-webpack的功能-webpack的初步使用) #课程目标 了解webpack出现的意义,以及webpack解决的前端问题 掌握webpack的使用流程和步骤 掌握we ...
- Tomcat9没有service.bat
下载个Windows版本的才有service.bat,默认是不带的. 附上tomcat9的下载地址: https://archive.apache.org/dist/tomcat/tomcat-9/v ...
- Kylin的特点
Kylin的特点 0.原理 从Hive读取数据,计算引擎可以用MapReduce 或者Spark, 把结果写入Hbase. 下次查询就会很快,也就是所谓的预计算. 1.为什么会有Kylin? hive ...
- Unity 2017 Scene界面与Game界面显示不同/过于灰暗的解决办法
场景界面的显示过于灰暗,严重影响工作心情. 切换到游戏界面时的颜色. 只要将场景中全部摄像机的[Allow HDR]取消勾选即可.
- Nginx timeout配置
缘由:客户测试反馈Request failed with status code 504,后续排查应该是nginx未配置超时设置 Step 1.打开nginx.conf查看 缺少keepalive_t ...
- Angular实战之使用NG-ZORRO创建一个企业级中后台框架(进阶篇)
前言: 上一篇文章我们讲了如何在创建的Angular项目中快速引入ng-zorro-antd企业中台组件库,并且快速构建后台管理页面框架模板.这一章主要介绍的是如何在创建好的后台管理页面框架的快速生成 ...
- 解决WebStorme点击谷歌浏览器图标无反应问题
解决思路: 在设置中重新设置谷歌浏览器路径,一定要选中到谷歌浏览器安装目录的Chrome.exe文件,选中后记得apply. 设置步骤: file->seeting->tools-> ...
- Eclipse中,No compiler is provided in this environment. Perhaps you are running on a JRE rather than a
问题说明 Eclipse导入Maven项目后,执行 mvn clean install后,出现如下错误: [INFO] ---------------------------------------- ...
- Java获取X509证书里的指纹(SHA-1)从pxf文件里面
直接通过流去获取pxf后缀文件的内容,指纹通过X509才能获取.String keyStorefile = "pfx文件地址";String strPassword = " ...
- JTable写入数据库内容
/*JTable中导入数据库数据. 创建2个Vector col和dat col存入字段名 dat存入数据内容. dbname=new JTable(dat,col); */package demo; ...