题目:
The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally decided to build an electoral wall for placing the posters and introduce the following rules:

  • Every candidate can place exactly one poster on the wall.
  • All posters are of the same height equal to the height of the wall; the width of a poster can be any integer number of bytes (byte is the unit of length in Bytetown).
  • The wall is divided into segments and the width of each segment is one byte.
  • Each poster must completely cover a contiguous number of wall segments.

They have built a wall 10000000 bytes long (such that there is enough place for all candidates). When the electoral campaign was restarted, the candidates were placing their posters on the wall and their posters differed widely in width. Moreover, the candidates started placing their posters on wall segments already occupied by other posters. Everyone in Bytetown was curious whose posters will be visible (entirely or in part) on the last day before elections. 
Your task is to find the number of visible posters when all the posters are placed given the information about posters' size, their place and order of placement on the electoral wall. 

 

Input

The first line of input contains a number c giving the number of cases that follow. The first line of data for a single case contains number 1 <= n <= 10000. The subsequent n lines describe the posters in the order in which they were placed. The i-th line among the n lines contains two integer numbers l i and ri which are the number of the wall segment occupied by the left end and the right end of the i-th poster, respectively. We know that for each 1 <= i <= n, 1 <= l i <= ri <= 10000000. After the i-th poster is placed, it entirely covers all wall segments numbered l i, l i+1 ,... , ri.
 

Output

For each input data set print the number of visible posters after all the posters are placed.

The picture below illustrates the case of the sample input. 

Sample Input

1
5
1 4
2 6
8 10
3 4
7 10

Sample Output

4

题目大意:给你一堵墙,长为10000000 ,再给你若干份海报,海报的高度与墙的高度一致,再给出贴海报的位置,先贴的海报可以被覆盖。问贴完后你能看到多少张海报(即没有完全被覆盖的海报有多少张)
     海报最多10000张,海报不会落在瓷砖中间(看上图容易理解) 解题思路:线段树+离散化+懒惰数组(线段树区间更新问题)
    我们把贴海报看成在墙上涂颜色,颜色用数字表示,比如贴第一张海报,col就为1,贴第二张海报,col就为2 把线段树的节点表示出来:l,r表示该点的区间,col是该区间的颜色,val为1代表该区间只有一种颜色,val为0代表该区间没有被涂色或有多种颜色

struct node{

int l,r,col,val;

} tree[MAXN*8];

线段树的样子(以区间1-10为例子)
   

我们用这棵树来演示一遍解样例的过程

首先是建树,每个节点都是无色的(col为0),每个节点的val都是0;
然后是更新,一张一张海报往上贴
贴第一张,头顶红色的节点是扫描过的节点,其中【1,3】【4,4】的val改为1,因为这些区域都只有一种颜色而且全覆盖了
(节点上的数字是val的值)
第一张【1,4】

贴第二张,头顶绿色的就是第二遍更新扫描过的节点,注意看蓝色圈圈的部分,对比一下上图,发现【1,2】【3,3】【1,1】【2,2】都画上了红线。

一开始【1,3】涂了颜色1,说明【1,1】【2,2】【3,3】都是涂了颜色1,但是上图中这3个区间并没有被访问,这就是因为懒嘛。。。。

等到再次访问【1,3】这个点,并且要继续往下走的时候,才把【1,3】下面的两个节点涂上色,再进行处理,有种不到ddl死活不肯干活的感觉

不用懒惰标记:贴一张【1,9】的海报,就要把除了【10,10】之外的节点都访问一遍,共18次

用了懒惰标记:贴一张【1,9】的海报,访问【1,10】【1,5】【6,10】【6,8】【9,10】【9,9】共6次

这就是懒惰标记的作用,它可以减少很多运算并保证答案的正确性

第二张【2,6】

贴第三张【8,10】

第四张【3,4】

第五张【7,10】

标记好了后开始查找query,找val=1的,每找到一个val等于1的就判断该颜色有没有出现过,如果该颜色没有出现过则num++,有则忽略,返回上一层;

这里搜索下来就是【1,1】1色,【2,2】2色,【3,3】3色,【4,4】3色,【5,5】2色,【6,6】2色,【7,7】5色,【8,8】5色,【9,10】5色

一共4中颜色,即有4张可见海报

离散化

这个只是样例的解法,如果放到整个问题中,第一个节点的区间范围为【1,10000000】,显然直接开数组存会TLE或者MLE

这个时候我们就要对数据进行离散化

个人对离散化的理解,就相当于映射,下面用样例来做解释

一开始,我们有1,4,2,6,8,10,3,4,7,10十个点

把他们按从小到大的顺序排列,变成1,2,3,4,4,6,7,8,10,10

然后从1开始,给每个不同的数字进行编号

可以看出,用离散化后的点完全可以表示原来的点(就是映射啦)

而原来的点区间为【1,10】

离散化后的点区间为【1,8】

这里看好像不明显,但如果一开始的点中3换成了10000000

那么原来的点区间为【1,10000000】

离散化后的点区间还是【1,8】

区别就体现出来了

题目中海报最多10000张,最多有20000个点

离散化后区间是【1,20000】

和一开始的【1,10000000 】相比,显然........

用离散化后的数来建树,按照上面的思路就可以解题了

代码

#include <iostream>
#include <algorithm>
#include <cmath>
#include <string.h>
#include <stdio.h>
using namespace std;
#define MAXN 10010
int N;
struct node{
int l,r,col,val;//线段树的节点,内容包括区间l和r的值,颜色col(即哪张海报),val=1表示【l,r】为单色,val=0表示【l,r】不是单色
}tree[MAXN*]; bool vis[MAXN];//判断该颜色是否出现过,查询时使用 struct point{
int a,n,f;//记录离散化前的点,a表示 点的值,n表示颜色(即哪张海报),f=0表示该点是区间左端点,f=1表示该点是区间右端点
}p[MAXN*]; struct san{
int l,r,col;//记录离散化后的线段,l,r是左右端点,col是颜色,下标表示哪张海报
}in[MAXN];
bool cmp(point a,point b)
{
return a.a <b.a ;
} void build(int l,int r,int rt)//l是左端点,r是右端点,rt是当前节点
{
tree[rt].l=l;
tree[rt].r=r;
tree[rt].val=;
tree[rt].col=;
if(l==r) return ;
int mid=(l+r)>>;
build(l,mid,rt<<);
build(mid+,r,rt<<|);
} void updata(int l,int r,int col,int rt)//l是更新的左端点,r是更新的右端点,col是更新的颜色,rt是当前节点
{
if(tree[rt].val&&tree[rt].col==col) return ;
//如果当前线段是单色而且 该线段的颜色和要更新的颜色一致,则不用改了,返回
if(tree[rt].l==l&&tree[rt].r==r){//找到要更新的线段
tree[rt].col=col;
tree[rt].val=;
return;
} if(tree[rt].val ){//懒惰标记,把懒惰标记打在2个孩子身上,自己的懒惰标记取消
tree[rt<<].val=tree[rt<<|].val=tree[rt].val;
tree[rt<<].col=tree[rt<<|].col=tree[rt].col;
tree[rt].val=;
} int mid=(tree[rt].l+tree[rt].r)>>;
if(l>mid) updata(l,r,col,rt<<|);//要更新的线段在右孩子上
else if(r<=mid) updata(l,r,col,rt<<);//要更新的线段在左孩子上
else {//要更新的线段在左右孩子上
updata(l,mid,col,rt<<);
updata(mid+,r,col,rt<<|);
}
} int query(int l,int r,int rt)
{
int col=tree[rt].col;
if(tree[rt].val){//线段单色
if(!vis[col]) {//该颜色没有出现过
vis[col]=;
return ;//该颜色出现了,查找多了一种颜色
}
else return ;//这种颜色出现过了
} int mid=(tree[rt].l+tree[rt].r)>>;
return query(l,mid,rt<<)+query(mid+,r,rt<<|);
//找左右孩子
} int main()
{
int M;
scanf("%d",&M);
while(M--)
{
scanf("%d",&N);
for(int i=;i<=N;++i){
int a,b;
scanf("%d %d",&a,&b);
p[*i-].a=a; p[*i-].n=i; p[*i-].f=;
p[*i].a=b; p[*i].n=i; p[*i].f=;
//存海报,一共有N条线段,2N个点
}
//离散化开始
sort(p+,p++*N,cmp);
p[].a=p[].a;//为循环设一个特殊条件
int num=,n,f;//num表示有多少个离散化后的点
for(int i=;i<=*N;++i){
n=p[i].n;
f=p[i].f;
if(p[i].a!=p[i-].a) num++;
if(!f) {//该点是起点
in[n].l=num;
in[n].col=n;
}
else {//该点是终点
in[n].r=num;
in[n].col=n;
}
}
//离散化结束
build(,num,);//建树,区间为【1,num】
for(int i=;i<=N;++i)//区间更新,相当于贴海报的过程
updata(in[i].l,in[i].r,in[i].col,); memset(vis,,sizeof(vis));
printf("%d\n",query(,num,));
} }
 

D - Mayor's posters(线段树+离散化)的更多相关文章

  1. POJ 2528 Mayor's posters(线段树+离散化)

    Mayor's posters 转载自:http://blog.csdn.net/winddreams/article/details/38443761 [题目链接]Mayor's posters [ ...

  2. poj 2528 Mayor's posters 线段树+离散化技巧

    poj 2528 Mayor's posters 题目链接: http://poj.org/problem?id=2528 思路: 线段树+离散化技巧(这里的离散化需要注意一下啊,题目数据弱看不出来) ...

  3. Mayor's posters (线段树+离散化)

    Mayor's posters Description The citizens of Bytetown, AB, could not stand that the candidates in the ...

  4. [poj2528] Mayor's posters (线段树+离散化)

    线段树 + 离散化 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayor ...

  5. Mayor's posters(线段树+离散化POJ2528)

    Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 51175 Accepted: 14820 Des ...

  6. POJ 2528 Mayor's posters (线段树+离散化)

    Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions:75394   Accepted: 21747 ...

  7. poj 2528 Mayor's posters 线段树+离散化 || hihocode #1079 离散化

    Mayor's posters Description The citizens of Bytetown, AB, could not stand that the candidates in the ...

  8. POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化)

    POJ.2528 Mayor's posters (线段树 区间更新 区间查询 离散化) 题意分析 贴海报,新的海报能覆盖在旧的海报上面,最后贴完了,求问能看见几张海报. 最多有10000张海报,海报 ...

  9. poj-----(2528)Mayor's posters(线段树区间更新及区间统计+离散化)

    Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 43507   Accepted: 12693 ...

  10. POJ2528:Mayor's posters(线段树区间更新+离散化)

    Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral electio ...

随机推荐

  1. spring boot 整合 百度ueditor富文本

    百度的富文本没有提供Java版本的,只给提供了jsp版本,但是呢spring boot 如果是使用内置tomcat启动的话整合jsp是非常困难得,今天小编给大家带来spring boot整合百度富文本 ...

  2. 4步解决“Microsoft Office Professional Plus 2013在安装过程中出错”

    公司新搭建了AD域,公司内使用了1年多的电脑,现在要加入域,加域过程问题错综复杂. 其中一台电脑上,反应说Excel经常卡住,严重影响使用,所以考虑重装office2013.在控制面板卸载了: 卸载完 ...

  3. 关于MySQL中的自联结的通俗理解

    关于MySQL中的自联结的通俗理解 前言:最近在通过SQL必知必会这本书学习MySQL的基本使用,在学习中也或多或少遇到了点问题,我也正好分享给大家,我的这篇博客用到的所有表格的代码都是来自SQL必知 ...

  4. STM32F103引脚功能定义

  5. 网络-03-端口号-linux端口详解大全--著名端口

    端口号码 / 层 名称 注释 1 tcpmux TCP 端口服务多路复用 5 rje 远程作业入口 7 echo Echo 服务 9 discard 用于连接测试的空服务 11 systat 用于列举 ...

  6. 使用jconsole监控JVM内存

    首先声明:此篇博文分析的是JDK1.8. JVM内存区域总体分两类:heap区和非heap区.Jconsole中对内存划分为同样的结构,如下: heap区又分为:  - Eden Space(伊甸园) ...

  7. Linux基础命令---free显示内存使用

    free free指令用来显示内存的使用情况,显示系统中可用和已使用的物理和交换内存的总量,以及内核使用的缓冲区.应该忽略共享内存列:它已经过时了. 此命令的适用范围:RedHat.RHEL.Ubun ...

  8. 7个优秀的国内外移动端web框架(转)

    淘宝SUI Mobile框架   (light7框架 官网:http://www.light7.cn/)官网地址:http://m.sui.taobao.org/ SUI Mobile 是一套基于 F ...

  9. CAN双机通讯调试小结(SJA1000与MCP2515通讯)

    2011-12-07 21:36:02. 效果图: 1,51的SJA1000自收自发测试完成,见上一篇小结. 2,SJA1000自测完成后,再自测MCP2515就非常容易.主要是设置工作模式为回环模式 ...

  10. .NET 常用ORM之NHibernate

    NHibernate做.Net应该都不陌生,今天我们就算是温故下这个技术,概念性的东西就不说了,这次主要说本人在实际使用的遇到的问题,比较费解现在就当是记录下,避免以后再犯.本次主要使用的情况是1对N ...