Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 59254   Accepted: 17167

Description

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 li 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 <= li <= ri <= 10000000. After
the i-th poster is placed, it entirely covers all wall segments numbered li, li+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

Source

【题解】

这题不要看题目描述。直接看图片和样例输入就能知道是什么意思了。

最后问最上面有多少种不同的海报??

然后1000W的int数组38MB.为了实现线段树。必然要开个4倍左右。

然后内存限制为64MB.会超!

为了解决内存问题。要用到离散化的知识。

比如样例输入的区间

1 4
2 6
8 10
3 4
7 10

可以得到端点1,2,3,4,6,7,8,10; (相同则只取一个就好,即剔除重复的)

当然这里省略了将端点升序排这个步骤。

然后我们给每个端点标一个序号

其实就是排序后的数组下标

即a[1]=1,a[2] = 2,a[3] = 3,a[4] = 4,a[5] = 6...以此类推。

a[]  =1 2 3 4 6 7 8 10

key =1 2 3 4 5 6 7 8

然后我们就可以把原来的区间写成

[1,4];

[2,5];

[7,8];

[3,4];

[6,8];

最后同样可以得到相同的结果。

而我们已经成功地把所给的巨大的区间端点和1..2*n对应起来了;

之后我们对在进行过离散化的区间进行覆盖就可以了。

覆盖的方法就是线段树了。

但是还有一个问题。就是离散化有一种情况会发生错解。

如下:

1,10

1,4

6,10

我们排序后得到

a[]  = 1 4 6 10

key= 1 2 3 4

则区间变为

[1,4]

[1,2]

[3,4]

看起来1,4已经被后面两个全部覆盖了。

但实际上

在未离散之前的坐标基础上

1,10还有一个点[5,5]未被覆盖。

如何解决呢?

其实就是因为4,6不是连续的。不能按照顺序他们标一个x和x+1;

那么我们可以在4和6之间加一个5;就变成了

a[]= 1 4 5 6 10

key=1 2 3 4 5

则原区间变成

[1,5]

[1,2]

[4,5]

这样我们就能知道还有一个点未被覆盖。

因为我们不知道会不会有这种情况。

所以

我们在将端点进行去重且排序过后。

如果a[i]>a[i-1]+1,则插入一个元素a[i-1]+1在a[i]和a[i-1]之间。i∈[2,x]x是key的最大值。

然后l[i],r[i]的检索key值的工作则可以用lower_bound函数来完成。

(二分查找并不好写,但是如果已经确定在序列中的应该会比较容易。所以手写也可以啦)

之后。进行线段树的操作。

设cover[i]表示i这个节点所在的区间覆盖了某种颜色。

如果寻找到的节点所在的区间被要求的区间所覆盖。

则将这个节点所代表的区间染上相应的颜色。

这个颜色可以作为lazy_tag来使用。之后一旦遇到一个这样的lazy_tag,就把儿子节点染成这个lazy_tag的标志。

然后父亲节点lazy_tag的标志改为-1,表示这个区间下面可能还有其他不同的颜色。不能一概而论了。

然后在询问的时候。如果遇到了那些能够"一概而论"的区间,就判断这个颜色是否出现过。如果没有出现过就递增答案。

最后输出答案就好。

特别注意;

一组数据,color啊,颜色的判重数组啊什么的都要重置。千万不要写在外面!!

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring> int T,n,a1[50000],l[20001],r[20001],color[200000],ans;
bool bo[20001]; void push_down(int rt)
{
if (color[rt] != -1) //如果之前有被染过色
{
color[rt << 1] = color[rt << 1 | 1] = color[rt];//把儿子节点的颜色改成这个父亲节点的颜色。
color[rt] = -1;//之后就不能一概而论了,因为接下来可能修改了这个节点所代表的区间内的一部分区间的颜色;
}
} void updata(int l, int r, int num,int begin, int end, int rt) //当前节点rt所代表的区间为[begin,end],然后所要染色的区间为[l,r]
{//要染成的颜色为num
if (l <= begin && end <= r)//如果当前节点所代表的区间在所要染色的区间内。
{
color[rt] = num;//则直接染色(因为在区间内,所以可以给这个区间"一概而论"地染成相同颜色)
return;
}
push_down(rt);//判断一下这个节点之前是否被染过色。
int m = (begin + end) >> 1;//取中点。
if (l <= m)
updata(l, r, num, begin, m, rt << 1);//如果这个节点所代表的区间的左半部分和所要染色的区间有交集。则往左不断逼近这个区间
if (m < r)
updata(l, r, num, m + 1, end, rt << 1 | 1);//如果右边有交集则同理。
} void query(int l, int r, int rt)//询问l,r这个区间内的颜色数目
{
if (color[rt] != -1)//如果这个节点所代表的区间内的颜色是相同的。
{
if (!bo[color[rt]])//如果之前没有计数过这个颜色
{
bo[color[rt]] = true;//标记为已经记录过
ans++;//递增答案。
}
return;
}
if (l == r)//如果左端点和右端点重合则结束。
return;
int m = (l + r) >> 1;//取中点
query(l, m, rt << 1);//往左儿子递增颜色
query(m + 1, r, rt << 1 | 1);//往右儿子递增颜色。
} int main()
{
scanf("%d", &T);//输入数据的组数
while (T--)//输入T组数据
{
memset(color, 255, sizeof(color));
a1[0] = 0;
scanf("%d", &n);//输入n个区间。
for (int i = 1; i <= n; i++)
{
scanf("%d%d", &l[i], &r[i]);
a1[0]++;//递增找到的端点个数
a1[a1[0]] = l[i];//把这个端点记录下来。
a1[0]++;
a1[a1[0]] = r[i];
}
std::sort(a1 + 1, a1 + 1 + 2 * n);//然后用sort函数讲其升序排。
a1[0] = 1;//然后要进行去重操作
for (int i = 2; i <= 2*n; i++)//这里的i一定是大于等于a1[0]的。所以不会对数据造成影响。
if (a1[i] != a1[i - 1])//直接判断是不是和前一个相等
{
a1[0]++;
a1[a1[0]] = a1[i];//不相等则加入。
}
int end = a1[0];
for (int i =2;i <= end;i++)//如果有前后不是连续的端点。则在这两个端点之间插入一个端点。
if (a1[i] > a1[i - 1] + 1)
{
a1[0]++;
a1[a1[0]] = a1[i - 1] + 1;
}
std::sort(a1 + 1, a1 + 1 + a1[0]);//说是插入操作,但实际上是加在数组的后面,所以排序一下。这样就等价于插入了
for (int i = 1; i <= n; i++)
{
l[i] = std::lower_bound(a1 + 1, a1 + 1 + a1[0], l[i]) - a1; //然后检索每个端点它的key值。
r[i] = std::lower_bound(a1 + 1, a1 + 1 + a1[0], r[i]) - a1;
updata(l[i], r[i],i, 1, a1[0], 1);//以这个key值作为新的区间,然后做线段树操作。即染色
}
ans = 0;
memset(bo, false, sizeof(bo));
query(1, a1[0], 1);//统计1..a[0]区间内的颜色种类;
printf("%d\n", ans);//输出答案。
}
return 0;
}

【poj2528】Mayor's posters的更多相关文章

  1. 【poj2528】Mayor's posters

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

  2. 【SDOJ 3741】 【poj2528】 Mayor's posters

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

  3. 【线段树】Mayor's posters

    [poj2528]Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 66154   Accept ...

  4. 【POJ 2528】Mayor’s posters(线段树+离散化)

    题目 给定每张海报的覆盖区间,按顺序覆盖后,最后有几张海报没有被其他海报完全覆盖.离散化处理完区间端点,排序后再给相差大于1的相邻端点之间再加一个点,再排序.线段树,tree[i]表示节点i对应区间是 ...

  5. 【hdu】Mayor&#39;s posters(线段树区间问题)

    须要离散化处理,线段树的区间改动问题. 须要注意的就是离散化的时候,由于给的数字是一段单位长度,所以须要特殊处理(由于线段的覆盖和点的覆盖是不一样的) 比方:(1,10)(1,4) (6,10) 离散 ...

  6. POJ2528 Uva10587 Mayor's posters

    The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign h ...

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

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

  8. 线段树---poj2528 Mayor’s posters【成段替换|离散化】

    poj2528 Mayor's posters 题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报 思路:这题数据范围很大,直接搞超时+超内存,需要离散化: 离散化简单的来说就是只取我们需要 ...

  9. POJ2528 Mayor&#39;s posters 【线段树】+【成段更新】+【离散化】

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

随机推荐

  1. 24. Spring Boot 事务的使用

    转自:https://blog.csdn.net/catoop/article/details/50595702

  2. select into from 与 insert into select 区别

    1.INSERT INTO SELECT语句 语句形式为:Insert into Table2(field1,field2,...) select value1,value2,... from Tab ...

  3. js常用数据转换&判断

    数组转字符串 var a, b; a = new Array(0,1,2,3,4); b = a.join("-"); //"0-1-2-3-4" 字符串转数组 ...

  4. python项目实战-小游戏1

    项目规则: 1.玩家和敌人分别从现有的角色中选择3个角色 2.随机生成目前的血量,和攻击量 3.游戏规则:当玩家向敌人发起攻击,敌人当前的血量=之前的血量-玩家的血量,同理 4.3局两胜 5.自定义玩 ...

  5. 洛谷 P1551 亲戚

                      洛谷 P1551 亲戚 题目背景 若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系. 题目描 ...

  6. FZU Problem 2062 Suneast & Yayamao

    http://acm.fzu.edu.cn/problem.php?pid=2062 题目大意: 给你一个数n,要求求出用多少个数字可以表示1~n的所有数. 思路: 分解为二进制. 对于一个数n,看它 ...

  7. POJ 2376 Cleaning Shifts 区间覆盖问题

    http://poj.org/problem?id=2376 题目大意: 给你一些区间的起点和终点,让你用最小的区间覆盖一个大的区间. 思路: 贪心,按区间的起点找满足条件的并且终点尽量大的. 一开始 ...

  8. 最新GitHub新手使用教程(Windows Git从安装到使用)——详细图解

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 一.叙述 1.Git简介 Git(读音为/gɪt/.)是一个开源的分布式版本控制系统,可以有效.高速地处理从很小到非常大的项目版本 ...

  9. Webpack学习手册

    多端阅读<Webpack官方文档>: 在PC/MAC上查看:下载w3cschool客户端,进入客户端后通过搜索当前教程手册的名称并下载,就可以查看当前离线教程文档.下载Webpack官方文 ...

  10. HibernateCRUD基础框架(2)-HQL语句构造器(HqlQueryBuilder,HqlUpdateBuilder)

    上篇讲述了最基本的实体类,本篇接着讲述HQL语句构造器,包括查询和更新等. 优点:通过面向对象的方式构造HQL语句,更快捷,不需要手动拼接HQL. 缺点:封装可能降低性能,只能支持常用的和较为简单的H ...