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. chocolatey 的安装与安装过程中的注意事项

    安装的windows需求 Windows 7+ / Windows Server 2003+ PowerShell v2+ .NET Framework 4+   注意:chocolatey的网站可能 ...

  2. liunx中安装禅道

    本文转自:https://www.cnblogs.com/bendouyao/p/10026746.html 一.准备工作 禅道安装包ZenTaoPMS.8.1.3.zbox_64.gz,上传至服务器 ...

  3. 五、Docker+Sqlserver

    原文:五.Docker+Sqlserver sqlserver现在支持linux了.所以可以运行在docker内 一.下载镜像: docker pull microsoft/mssql-server- ...

  4. Codeforces Round #100 E. New Year Garland (第二类斯特林数+dp)

    题目链接: http://codeforces.com/problemset/problem/140/E 题意: 圣诞树上挂彩球,要求从上到下挂\(n\)层彩球.已知有\(m\)种颜色的球,球的数量不 ...

  5. window.location无法跳转页面的问题

    最近在使用 window的location时碰到一个无法跳转页面的问题, 后来在location语句后加了一条这样的语句:window.event.returnValue = false;然后竟然可以 ...

  6. 芯片TPS76030、TPS76032、TPS76033、TPS76038、TPS76050 电源芯片

    下图是从网上摘出来的图片:TPS76033 它的作用就是改变电压: 输入电压:3.5V到16V       通过芯片的处理后     输出电压:3.3V 要学会看图,从中提取有用的信息 再看一个数据手 ...

  7. JS错误记录 - 微博发布

    <style> *{ margin: 0; padding: 0;} #ul1{ width: 400px; height: 400px; border: 1px solid #000; ...

  8. (转)linux的一个find命令配合rm删除某天前的文件

    转自:http://www.cnblogs.com/mingforyou/p/3930624.html 语句写法:find 对应目录 -mtime +天数 -name "文件名"  ...

  9. 使用Surging Mqtt 开发基于WS的MqttClient客户端

    原文:使用Surging Mqtt 开发基于WS的MqttClient客户端 最近一段时间由于要做一套智能设备系统,而有幸了解到Surging中的Mqtt broker,学习了很多东西本篇文章基于Su ...

  10. 微服务实战(一):微服务架构的优势与不足 - DockOne.io

    原文:微服务实战(一):微服务架构的优势与不足 - DockOne.io [编者的话]本文来自Nginx官方博客,是微服务系列文章的第一篇,主要探讨了传统的单体式应用的不足,以及微服务架构的优势与挑战 ...