title: poj-2528线段树练习
date: 2018-10-13 13:45:09
tags:

  • acm
  • 刷题
    categories:
  • ACM-线段树

概述

这道题坑了我好久啊啊啊啊,,,,

到现在也只是理解了kaungbin的代码,,,知道每一步做什么,,,但感觉就是哪里有些不对劲的样子,,,,

这道题有两个点是我感觉很重要的,,,一个是数据的离散化,,,另一个是线段树的变形,,,也就是它所维护的东西和之前见过的不一样了,,,,

分析思路

题意是这样的,,,在一个很大的区间里,,,不停的给每一个区间覆盖海报,,,每个覆盖的海报是不一样的,,然后问你最后一共有几个海报是露出来的,,,

大体上的思路是与所给贴海报相反的顺序贴海报,,,这样的话第一张(也就是原来顺序的最后一张)一定是全露出来的,,然后第二张(也就是原来顺序的倒数第二张)如果是在第一张的区间里说明它就被完全覆盖了,,如果是在第一张以外的其他地方,,,就说明这张也一定是露出来的,,,以此类推,,对于每一次判断出是露出来的++ans,,,最终全处理了就得到了答案,,,数据要离散后再用,,,

可以看出这样的写法中线段树只是用来判断每一次的贴海报,,,也就是说,,,线段树只是用来维护每一个区间是否被覆盖(更新),,,同时返回所要覆盖的区间是否有露出来的(查询),,,所以更新和查询的操作可以合并在一起,,,,

实现

数据的离散化

先说一下离散怎么实现:

首先原数据保存到x[maxn]数组,,,

然后把所有的数据复制到另一个数组a[maxn],,,

对其排序,,,

去重,,,

然后对去重的数组a[maxn]遍历进行离散,,,

这样想要知道知道原来数据中x所对应离散后的位置就为hash[x],,,

sort(a , a + count);
count = unique(a , a + count) - a;
for(int i = 0; i < count; ++i)hash[a[i]] = i;

最后的代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>using namespace std;
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
const int maxn = 1e5 + 10;
struct node
{int l;int r;bool cov;       //表示这个节点所代表的区间是否被覆盖
}node[maxn << 2];struct poster       //表示海报的结构体
{int l;int r;
}poster[maxn << 2];void build(int rt , int l , int r)
{node[rt].l = l;node[rt].r = r;node[rt].cov = false;   //每一个区间初始化为未覆盖if(l == r)  return;int mid = (l + r) >> 1;build(lson);build(rson);
}bool post(int rt , int l , int r)
{//当前节点,所要覆盖的额区间[l , r]if(node[rt].cov)    return false;                   //若这个区间已经被覆盖直接返回if(node[rt].l == l && node[rt].r == r){node[rt].cov = true;                            //未覆盖的前提下找到整个区间时return true;}bool res;int mid = (node[rt].l + node[rt].r) >> 1;if(r <= mid)    res = post(rt << 1 , l , r);else if(l > mid)res = post(rt << 1 | 1 , l , r);else{bool r1 = post(rt << 1 , l , mid);bool r2 = post(rt << 1 | 1 , mid + 1 , r);res = r1 || r2;                                 //当跨两个区间时,,,要分别判断是否都是被覆盖的,,有一个没覆盖即露出就说明这个区间有露出的}if(node[rt << 1].cov && node[rt << 1 | 1].cov)      //两个子区间都露出父节点也是露出node[rt].cov = true;return res;
}int a[maxn];
int hash[10000010];int main()
{int T;scanf("%d" , &T);while(T--){int n;scanf("%d" , &n);int count = 0;for(int i = 0; i < n; ++i){scanf("%d%d" , &poster[i].l , &poster[i].r);a[count++] = poster[i].l;a[count++] = poster[i].r;//相邻存点}//离散sort(a , a + count);count = unique(a , a + count) - a;for(int i = 0; i < count; ++i)hash[a[i]] = i;build(1 , 0 , count - 1);int ans = 0;for(int i = n - 1; i >= 0; --i)             //反着遍历,,有露出的就增一if(post(1 , hash[poster[i].l] , hash[poster[i].r]))++ans;printf("%d\n" , ans);}
}//一个缺点,,,这样单纯的离散数据会出错,,,像这一组,,,
//但是poj上没有考虑这种情况,,,,应该是标程的离散也是这样把,,,,,,
//3
//1 10
//1 3
//6 10
//2
//应该是3

总结

  • 暑假时接触过一次数据的离散化,,,但是当时只是会用就行,,,最终还是忘记了,,,只知道这样一个名词,,,这次花了点时间记忆了一下,,,但是还是没有仔细深入的看看,,,因为以前看到的离散化时用的lower_bound(),,,,而且操作更加的复杂,,,过一段时间再看看把,,,,

  • 看到网上好多人用的线段树的结构和之前写的那样一样,,,build(),update(),query(),,,但就是理解不了,,,QAQ,,,看了kuangbin的写法反到理解了,,,虽然基本是照搬过来的,,,,再过几天要重写一遍,,,

(end)

转载于:https://www.cnblogs.com/31415926535x/p/9782804.html

poj-2528线段树练习相关推荐

  1. POJ - 2528 线段树+离散化

    其实很早就在白书上的常用技巧上 看到离散化的操作,但是之前一直没遇到过需要离散化的题目(应该是我太菜的缘故),所以一直也没怎么重视,下面说说这道题目的考点,也就是离散化. 什么是离散化呢?请先自行百度 ...

  2. poj 2528 线段树离散化+染色

    题目链接 Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 92628 Accepted: 2645 ...

  3. poj pku 2528 线段树的基础应用

    郁闷了一上午的题目,一直都是WA,找了老半天错,想了很多测试数据还是WA.就连骑单车回家的路上还在想这题.悲剧呀... 做完这个题目才明白线段树不同于其他算法,它只是一种思想,在实际应用中是要根据题意 ...

  4. POJ 3468 线段树+lazy标记

    lazy标记   Time Limit:5000MS     Memory Limit:131072KB     64bit IO Format:%I64d & %I64u  Submit S ...

  5. POJ 3264 线段树

    题意 传送门 POJ 3264 题解 线段树维护区间的最大值和最小值即可. #include <cstdio> #include <cstring> #include < ...

  6. poj(2325)线段树

    这里介绍另外一种解法,此题可以用线段树,可以用树状数组 其实这题求的都是下面的和左面的,线段树这种数组结构刚好可以满足,为什么呢?这里稍微解释下吧,也有助于以后的复习 看上面这个图,[1,1],[2, ...

  7. poj 3468 线段树

    线段树的 建立build(初始化+左右相等+两个递归+别忘了sum)+更新update(递归出口+更新delta+三向递归+修正当前节点的value)+查找query(如果左右相等+更新delta+三 ...

  8. poj 2777(线段树+区间染色)

    解题思路:这道题利用了线段树+位运算的思想,由于颜色的种类只有30种,所以int可以存下来,所以我们在线段树的节点里面加上status的状态信息,表示这段区间内的颜色信息,而且我们可以知道,父节点的s ...

  9. poj 2352 线段树

    注意到题目中给的y是递增的,那个y没什么用,直接线段树维护一段1,x的区间. #include<string> #include<iostream> #include<c ...

  10. A Simple Problem with Integers POJ - 3468 (线段树)

    思路:线段树,区间更新,区间查找 1 #include<iostream> 2 #include<vector> 3 #include<string> 4 #inc ...

最新文章

  1. Oracle --存储过程,输入不定个数参数
  2. 车辆颜色识别学习笔记
  3. c/c++实现一个密集型server/socket多路复用select
  4. PE学习(六)第六章 栈与重定位表 实例栈溢出、模拟加载器加载DLL、遍历重定位表
  5. openshift 部署_在OpenShift上部署Java EE微服务
  6. caffe common 程序分析 类中定义类
  7. 【LeetCode笔记】剑指 Offer 93. 复原 IP 地址(Java、DFS、字符串)
  8. vue中cookie的使用——将cookie放在请求头header中
  9. 语言软件生成outsid_常用的C语言开发工具有哪些
  10. (转)Ubuntu10.04编译FFmpeg
  11. MATLAB中的概率函数
  12. 阿里45K高级Java岗,必备技能清单
  13. 全网最全的 Java 技术栈内容梳理(持续更新中)
  14. win7 系统打开文件扩展名
  15. 大班音乐机器人反思_幼儿园大班音乐游戏教案活动《机器人》含反思
  16. 根据线索整理的一套在2021年继续使用Flash Player的方法(20.12.29更新)
  17. 【第 001 期 · 文献领读】——MRI专题
  18. 级联h桥储能,soc均衡,soc均衡控制,相内soc均衡,相间soc均衡,蓄电池充放电控制,恒压充电,恒流充电,零序电压注入法相间soc均衡
  19. vue-router 采坑记录
  20. 前端视频预览功能的实现

热门文章

  1. Javascript 对象一(对象详解)
  2. PWA(Progressive Web App)入门系列:(四)Promise
  3. 如何用DOS命令批量删除文件?(_desktop.ini 或 thumbs.db)
  4. [转]Android Activity和Intent机制学习笔记
  5. 更改微信小程序的基础版本库;更改uni-app小程序基础库;更改用户的微信小程序基础库最低版本;设置用户的微信小程序版本库;
  6. 重学java基础第六课:markdown语法
  7. 前端学习(3345):设计模式之工厂模式2
  8. React开发(139):ant design学习指南之下载文件
  9. [html] 你有使用过webp的图片格式吗?
  10. [css] 怎么去掉点击a链接或者图片出现的边框?