【poj2528】Mayor's posters
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 59254 | Accepted: 17167 |
Description
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 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
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的更多相关文章
- 【poj2528】Mayor's posters
Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 64939 Accepted: 18770 ...
- 【SDOJ 3741】 【poj2528】 Mayor's posters
Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral electio ...
- 【线段树】Mayor's posters
[poj2528]Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 66154 Accept ...
- 【POJ 2528】Mayor’s posters(线段树+离散化)
题目 给定每张海报的覆盖区间,按顺序覆盖后,最后有几张海报没有被其他海报完全覆盖.离散化处理完区间端点,排序后再给相差大于1的相邻端点之间再加一个点,再排序.线段树,tree[i]表示节点i对应区间是 ...
- 【hdu】Mayor's posters(线段树区间问题)
须要离散化处理,线段树的区间改动问题. 须要注意的就是离散化的时候,由于给的数字是一段单位长度,所以须要特殊处理(由于线段的覆盖和点的覆盖是不一样的) 比方:(1,10)(1,4) (6,10) 离散 ...
- POJ2528 Uva10587 Mayor's posters
The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign h ...
- POJ 2528 Mayor's posters(线段树+离散化)
Mayor's posters 转载自:http://blog.csdn.net/winddreams/article/details/38443761 [题目链接]Mayor's posters [ ...
- 线段树---poj2528 Mayor’s posters【成段替换|离散化】
poj2528 Mayor's posters 题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报 思路:这题数据范围很大,直接搞超时+超内存,需要离散化: 离散化简单的来说就是只取我们需要 ...
- POJ2528 Mayor's posters 【线段树】+【成段更新】+【离散化】
Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 39795 Accepted: 11552 ...
随机推荐
- 玩转Bootstrap(基础) -- (6.导航条基础)
1.导航条样例 <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" ...
- hashlib —— Python 的 md5 和 sha1 加密
python的md5和sha1加密 0. md5 与 sha1 MD5 的全称是 Message-Digest Algorithm 5(信息-摘要算法).128 位长度.目前 MD5 是一种不可逆算法 ...
- HTML基础第十一讲---背景标志
转自:https://i.cnblogs.com/posts?categoryid=1121494 您是否老觉得网页「空空的」,没错!一个可能是我们还没有很多内容,另一个可能则是我们还没有设定网页背景 ...
- css的三种表现形式
1.行内样式(内嵌样式):结构的内部,即写在标签内的样式:写在标签的开始部分内部,style属性当中:<标记 style="样式的属性名1:样式的属性值1:属性名2:属性值2:.... ...
- 【2017 Multi-University Training Contest - Team 10 】Monkeys
[链接]点击打开链接 [题意] 给你一棵n节点的树,现在让你放k个猴子,可以删边,问最少可以剩余几条边,放k个猴子,满足任意一个猴 子至少与一只猴子相连.2<=k<=n<=1e5 [ ...
- h5做app和原生app有什么区别?
h5做app和原生app有什么区别? 一.总结 一句话总结: 二.h5做app和原生app有什么区别? 普通的HTML5技术与原生技术相比,有跨平台.动态.开放.直达二级内容页面等特点,但却在性能.工 ...
- 添加asp.net mvc到现有的asp.net web form 应用程序
前言 asp.net mvc的前一版本为asp.net web Form(Asp.net mvc之前称为asp.net),其第一个版本与2002年年初发布.asp.net web form 属于.ne ...
- 截止频率-3db
关于-3db截止频率 (2013-06-22 10:47:02) 转载▼ 分类: 信号.电路 关于-3db截止频率 为什么当信号衰减了-3db的时候就算是截止频率了.这里面有什么高深的内涵.毕竟这 ...
- 编程——C语言的问题,堆栈
堆和栈的区别一.预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结 ...
- (转)bat批处理的注释语句
在批处理中,段注释有一种比较常用的方法: goto start = 可以是多行文本,可以是命令 = 可以包含重定向符号和其他特殊字符 = 只要不包含 :start 这一行,就都是注释 :start 另 ...