【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 ...
随机推荐
- 三、Docker镜像的相关操作
原文:三.Docker镜像的相关操作 一.查看本地镜像: docker images 二.使用某个镜像来运行容器: docker run -t -i xxxx(镜像名):xx.xx(版本,不带即最新) ...
- Maven搭建hadoop环境报Missing artifact jdk.tools:jdk.tools:jar:1.7
今天,更新了工程,报错了. 项目中用了HBase,也有Hadoop相关的jar配置. pom文件, Missing artifact jdk.tools:jdk.tools:jar:1.7 Maven ...
- 【习题 7-8 UVA-12107】Digit Puzzle
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 迭代加深搜索. 枚举最大层数.(也即改变的数字个数 然后枚举第一个改哪个数字,第二个改哪个数字.. 一定要注意字典序问题. 每次优先 ...
- spring+mybatis+Atomikos JTA事务配置说明
一.概览 Atomikos是一个公司名字,旗下最著名的莫过于其Atomikos的事务管理器产品.产品分两个:一个是开源的TransactionEssentials,一个是商业的ExtremeTrans ...
- C++基于矢量图形库cairo画图图形
//sudo apt-get install libcairo2-dev //pkg-config --cflags --libs cairo //-I/usr/include/cairo -I/us ...
- meld文件的脚本
今天模仿着别人的脚本,结合网上的资料,摸索着写了一个简单的脚本,用来打开meld 工具.这个脚本虽然简单,但这是第一次自己写脚本,记录下来,作为自己python学习的起点.代码如下 #/use/bin ...
- 116.C语言异常抛错
#include <stdlib.h> #include <stdio.h> #include <setjmp.h> //异常抛错检测 jmp_buf buf1; ...
- Solr 倒排索引
正排索引(正向索引):正排表是以文档的ID为关键字,表中记录文档中每个字的位置信息,查找时扫描表中每个文档中字的信息直到找出所有包含查询关键字的文档. 正排表结构如图1所示,这种组织方法在建立索引的 ...
- 洛谷 P1192 台阶问题
P1192 台阶问题 题目描述 有N级的台阶,你一开始在底部,每次可以向上迈最多K级台阶(最少1级),问到达第N级台阶有多少种不同方式. 输入输出格式 输入格式: 输入文件的仅包含两个正整数N,K. ...
- Excel 下拉菜单制作
废话少说吧,以图明示: 图1 操作步骤(环境为Office 2013) 备注,第四步,可以选择页面中的数据源,也可以以“,”分割的方式输入字符串 图2 制作效果