POJ 2528 Mayor's posters 离散化+线段树
题目大意:给出一些海报和贴在墙上的区间。问这些海报依照顺序贴完之后,最后能后看到多少种海报。
思路:区间的范围太大,然而最多仅仅会有10000张海报,所以要离散化。
之后用线段树随便搞搞就能过。
关键是离散化的方法,这个题我时隔半年才A掉,之前一直就TTT,我还以为是线段树写挂了。
当我觉得我自己的水平这样的水线段树已经基本写不挂的时候又写了这个题,竟然还是T。
后来我对照别人的代码,才发现是我的离散化写渣了。
以下附AC代码(79ms),这个离散化写的比較优雅。时间也非常快,以后就这么写了。
CODE(POJ 79ms):
#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
#define LEFT (pos << 1)
#define RIGHT (pos << 1|1)
using namespace std; pair<int,int> interval[MAX];
pair<int,int *> src[MAX << 1]; int cases;
int tree[MAX << 2];
int intervals;
int cnt,t;
bool color[MAX]; inline void Initialize()
{
t = cnt = 0;
memset(color,false,sizeof(color));
memset(tree,0,sizeof(tree));
} inline void PushDown(int pos)
{
if(tree[pos]) {
tree[LEFT] = tree[pos];
tree[RIGHT] = tree[pos];
tree[pos] = 0;
}
} inline void Modify(int l,int r,int x,int y,int pos,int c)
{
if(l == x && y == r) {
tree[pos] = c;
return ;
}
PushDown(pos);
int mid = (l + r) >> 1;
if(y <= mid) Modify(l,mid,x,y,LEFT,c);
else if(x > mid) Modify(mid + 1,r,x,y,RIGHT,c);
else {
Modify(l,mid,x,mid,LEFT,c);
Modify(mid + 1,r,mid + 1,y,RIGHT,c);
}
} void GetAns(int l,int r,int pos)
{
if(tree[pos]) {
color[tree[pos]] = true;
return ;
}
if(l == r) return ;
int mid = (l + r) >> 1;
GetAns(l,mid,LEFT);
GetAns(mid + 1,r,RIGHT);
} int main()
{
for(cin >> cases; cases; --cases) {
scanf("%d",&intervals);
Initialize();
for(int i = 1; i <= intervals; ++i) {
scanf("%d%d",&interval[i].first,&interval[i].second);
src[++cnt] = make_pair(interval[i].first,&interval[i].first);
src[++cnt] = make_pair(interval[i].second,&interval[i].second);
}
sort(src + 1,src + cnt + 1);
for(int i = 1; i <= cnt; ++i)
{
if(src[i].first != src[i - 1].first) ++t;
*src[i].second = t;
}
for(int i = 1; i <= intervals; ++i)
Modify(1,cnt,interval[i].first,interval[i].second,1,i);
GetAns(1,cnt,1);
int ans = 0;
for(int i = 1; i <= intervals; ++i)
ans += color[i];
printf("%d\n",ans);
}
return 0;
}
为了警醒后人,也为了警醒自己(以后再也不这么写离散化了)。我将我T的离散化代码也发上来,好孩子千万不要学习。
CODE(POJ TLE):
#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 1000010
#define LEFT (pos << 1)
#define RIGHT (pos << 1|1)
using namespace std; pair<int,int> interval[MAX];
map<int,int> G; int cases;
int tree[MAX << 2];
int intervals,src[MAX << 1];
int cnt,t;
bool color[MAX]; inline void Initialize()
{
G.clear();
t = cnt = 0;
memset(color,false,sizeof(color));
memset(tree,0,sizeof(tree));
} inline void PushDown(int pos)
{
if(tree[pos]) {
tree[LEFT] = tree[pos];
tree[RIGHT] = tree[pos];
tree[pos] = 0;
}
} inline void Modify(int l,int r,int x,int y,int pos,int c)
{
if(l == x && y == r) {
tree[pos] = c;
return ;
}
PushDown(pos);
int mid = (l + r) >> 1;
if(y <= mid) Modify(l,mid,x,y,LEFT,c);
else if(x > mid) Modify(mid + 1,r,x,y,RIGHT,c);
else {
Modify(l,mid,x,mid,LEFT,c);
Modify(mid + 1,r,mid + 1,y,RIGHT,c);
}
} void GetAns(int l,int r,int pos)
{
if(tree[pos]) {
color[tree[pos]] = true;
return ;
}
if(l == r) return ;
int mid = (l + r) >> 1;
GetAns(l,mid,LEFT);
GetAns(mid + 1,r,RIGHT);
} int main()
{
for(cin >> cases; cases; --cases) {
scanf("%d",&intervals);
Initialize();
for(int i = 1; i <= intervals; ++i) {
scanf("%d%d",&interval[i].first,&interval[i].second);
src[++cnt] = interval[i].first;
src[++cnt] = interval[i].second;
}
sort(src + 1,src + cnt + 1);
G[src[1]] = ++t;
for(int i = 2; i <= cnt; ++i)
if(src[i] != src[i - 1])
G[src[i]] = ++t;
for(int i = 1; i <= intervals; ++i)
Modify(1,cnt,G[interval[i].first],G[interval[i].second],1,i);
GetAns(1,cnt,1);
int ans = 0;
for(int i = 1; i <= intervals; ++i)
ans += color[i];
printf("%d\n",ans);
}
return 0;
}
后来我和小伙伴门一起研究了这样的离散化方法,正常来说是不会T的,尽管多带了一个log。可是这个题是多组数据啊。坑啊,每一组数据就要clear一下map。据老师说map的clear是一个一个删的。。
。于是机制的我就每次new一个map,这样就不用clear了。结果交上去果然A了。
CODE(POJ 344ms):
#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 1000010
#define LEFT (pos << 1)
#define RIGHT (pos << 1|1)
using namespace std; pair<int,int> interval[MAX];
map<int,int> *G; int cases;
int tree[MAX << 2];
int intervals,src[MAX << 1];
int cnt,t;
bool color[MAX]; inline void Initialize()
{
G = new map<int,int>;
t = cnt = 0;
memset(color,false,sizeof(color));
memset(tree,0,sizeof(tree));
} inline void PushDown(int pos)
{
if(tree[pos]) {
tree[LEFT] = tree[pos];
tree[RIGHT] = tree[pos];
tree[pos] = 0;
}
} inline void Modify(int l,int r,int x,int y,int pos,int c)
{
if(l == x && y == r) {
tree[pos] = c;
return ;
}
PushDown(pos);
int mid = (l + r) >> 1;
if(y <= mid) Modify(l,mid,x,y,LEFT,c);
else if(x > mid) Modify(mid + 1,r,x,y,RIGHT,c);
else {
Modify(l,mid,x,mid,LEFT,c);
Modify(mid + 1,r,mid + 1,y,RIGHT,c);
}
} void GetAns(int l,int r,int pos)
{
if(tree[pos]) {
color[tree[pos]] = true;
return ;
}
if(l == r) return ;
int mid = (l + r) >> 1;
GetAns(l,mid,LEFT);
GetAns(mid + 1,r,RIGHT);
} int main()
{
for(cin >> cases; cases; --cases) {
scanf("%d",&intervals);
Initialize();
for(int i = 1; i <= intervals; ++i) {
scanf("%d%d",&interval[i].first,&interval[i].second);
src[++cnt] = interval[i].first;
src[++cnt] = interval[i].second;
}
sort(src + 1,src + cnt + 1);
(*G)[src[1]] = ++t;
for(int i = 2; i <= cnt; ++i)
if(src[i] != src[i - 1])
(*G)[src[i]] = ++t;
for(int i = 1; i <= intervals; ++i)
Modify(1,cnt,(*G)[interval[i].first],(*G)[interval[i].second],1,i);
GetAns(1,cnt,1);
int ans = 0;
for(int i = 1; i <= intervals; ++i)
ans += color[i];
printf("%d\n",ans);
}
return 0;
}
POJ 2528 Mayor's posters 离散化+线段树的更多相关文章
- poj 2528 Mayor's posters 【线段树 + 离散化】
Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 50643 Accepted: 14675 ...
- POJ 2528 Mayor's posters 离散化和线段树题解
本题就是要往墙上贴海报,问最后有多少可见的海报. 事实上本题的难点并非线段树,而是离散化. 由于数据非常大,直接按原始数据计算那么就会爆内存和时间的. 故此须要把数据离散化. 比方有海报1 6 7 ...
- poj2528 Mayor's posters(线段树,离散化)
离散化的思想: 对于这样的数据 (3,10000). (9,1000000). (5.100000), (1,1000). (7,1000000) 我们能够将其处理为 (2,7). (5,9). (3 ...
- poj 2528 Mayor's posters
这个题意是市长竞选,然后每一个人都能够贴广告牌.能够覆盖别人的看最后剩几个广告牌 这题目想了两个多小时,最后忍不住看了一下题解. 发现仅仅是简单地hash 和线段树成段更新 由于有10000个人竞选 ...
- 【hdu】Mayor's posters(线段树区间问题)
须要离散化处理,线段树的区间改动问题. 须要注意的就是离散化的时候,由于给的数字是一段单位长度,所以须要特殊处理(由于线段的覆盖和点的覆盖是不一样的) 比方:(1,10)(1,4) (6,10) 离散 ...
- 线段树区间更新,区间统计+离散化 POJ 2528 Mayor's posters
题意:有一个非常长的板子(10000000长),在上面贴n(n<=10000)张海报.问最后从外面能看到几张不同的海报. 由于板子有10000000长,直接建树肯定会爆,所以须要离散化处理,对于 ...
- POJ2528 Mayor's posters 【线段树】+【成段更新】+【离散化】
Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 39795 Accepted: 11552 ...
- 【POJ】2528 Mayor's posters ——离散化+线段树
Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Description The citizens of Bytetown, A ...
- Mayor's posters(离散化线段树)
Mayor's posters Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 54067 Accepted: 15713 ...
随机推荐
- 微信小程序开发教程(一)准备
1.成为微信公众平台开发者 成为微信公众平台的开发者,是小程序开发的首要条件.只有成为微信公众平台的开发者,才可以使用公众平台的各种开发接口.如果你已经是开发者,则可以跳过本章. ①.进入微信公众平台 ...
- 【贪心】【线性基】bzoj2844 albus就是要第一个出场
引用题解:http://blog.csdn.net/PoPoQQQ/article/details/39829237 注意评论区. #include<cstdio> using names ...
- 【二分图判定】hdu3478 Catch
详细的题解:http://www.docin.com/p-517243379.html 一个图是二分图 等价于 其至少有两个节点且没有奇环. 二分图判定的方法:从任意点出发进行一次dfs黑白染色,若某 ...
- 【矩阵乘法+快速乘】BZOJ2875-[NOI2012]随机数生成器
[题目大意] 已知Xn+1=(aXn+c) mod m,求Xn mod g. [思路] get到了longlong乘法的正确方法,快速乘.什么是快速乘呢? 简单来讲,快速幂就是模拟了二进制的竖式乘法. ...
- 零基础带你看Spring源码——IOC控制反转
本章开始来学习下Spring的源码,看看Spring框架最核心.最常用的功能是怎么实现的. 网上介绍Spring,说源码的文章,大多数都是生搬硬推,都是直接看来的观点换个描述就放出来.这并不能说有问题 ...
- 【R笔记】order函数例子
问题: R中提供的例子不太懂,为什么得出的结果是6 5 2 1 7 4 10 8 3 9呢? (ii <- order(x <- c(1,1,3:1,1:4,3), y & ...
- sql-server-on-linux-how-i-think-they-did-it : Anthony Nocentino's Blog
http://www.sqlservercentral.com/blogs/anthony-nocentinos-blog/2016/11/21/sql-server-on-linux-how-i-t ...
- iis日志字段解析
IIS日志字段 #Software: Microsoft Internet Information Services 7.5 #Version: 1.0 #Date: 2013-08-21 01:00 ...
- Telnet窗口尺寸选项
转:http://www.cnpaf.net/Class/Telnet/200408/6.html 1.命令名称和选项代码 名称=NAWS(NegotiateAboutWindowSize)协商窗口的 ...
- 一个 关于 case when的SQL
[例]从stud_grade表中查询所有同学考试成绩情况,凡成绩为空者输出“未考”.小于60分输出“不及格”.60分至70分输出“及格”.70分至90分输出“良好”.大于或等于90分时输出“优秀”. ...