本文为原创,转载请注明:http://www.cnblogs.com/kylewilson/

题目出处:

https://www.vijos.org/p/1103

题目描述:

一条马路从数轴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题解【线段树】的更多相关文章

  1. POJ2182题解——线段树

    POJ2182题解——线段树 2019-12-20 by juruoOIer 1.线段树简介(来源:百度百科) 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线 ...

  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 ...

  10. Poj 3468-A Simple Problem with Integers 线段树,树状数组

    题目:http://poj.org/problem?id=3468   A Simple Problem with Integers Time Limit: 5000MS   Memory Limit ...

随机推荐

  1. Java带Body内容的Http请求

    使用Java进行Http请求: package test2; import com.mashape.unirest.http.HttpResponse; import com.mashape.unir ...

  2. [从源码学设计]蚂蚁金服SOFARegistry 之 自动调节间隔周期性任务

    [从源码学设计]蚂蚁金服SOFARegistry 之 自动调节间隔周期性任务 目录 [从源码学设计]蚂蚁金服SOFARegistry 之 自动调节间隔周期性任务 0x00 摘要 0x01 业务领域 0 ...

  3. 工具-绿色使用软件等-破解pycharm,idea等Jet brain出品软件(99.2.1)

    1.下载此文件链接:https://pan.baidu.com/s/12nbtgeWiD1xKMtPIr-S1-g密码:b66f 并将 JetbrainsCrack-3.1-release-enc.j ...

  4. 注解 @CrossOrigin

    在Controller中看到@CrossOrigin ,这是什么?有什么用?为什么要用? what? @CrossOrigin是用来处理跨域请求的注解 先来说一下什么是跨域: (站在巨人的肩膀上) 跨 ...

  5. EF生成模型时Disigner中无信息

    原博文 http://blog.sina.com.cn/s/blog_a1b63a730101ezs4.html 说明 DbContext是对ObjectContext的简化封装.原来的ObjectC ...

  6. C#中Newtonsoft.Json 序列化和反序列化 时间格式

    步骤 引用 using Newtonsoft.Json; using Newtonsoft.Json.Converters; 格式配置 IsoDateTimeConverter timeFormat ...

  7. [论文分享] DHP: Differentiable Meta Pruning via HyperNetworks

    [论文分享] DHP: Differentiable Meta Pruning via HyperNetworks authors: Yawei Li1, Shuhang Gu, etc. comme ...

  8. 第一个开源控件:Google 官方下拉刷新控件 SwipeRefreshLayout 强化版,支持上拉刷新

    最近比较闲,所以趁着这时间撸了个SwipeRefreshLayout的加强版,Github地址. 原版只支持下拉刷新,强化之后支持上拉刷新和一进入页面就加载刷新,整个控件的加载动画是一致的,毫无违和感 ...

  9. 基于docker,consul,consul-template, registrator, nginx服务注册发现集群

      介绍 该工程主要实现服务的自动注册发现,从而达到提高运维效率,做到服务的自动发现和动态扩展. 服务注册发现 服务启动后自动被发现 动态变更负载均衡 自动伸缩 工具 1.Registrator 这是 ...

  10. device_create为何可以在/sys/class/具体类/属性文件?怎么实现的

    答案: 版本3.6.9: device_create -> device_register -> device_add -> device_add_attrs -> devic ...