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 ...
随机推荐
- Xamarin XAML语言教程构建ControlTemplate控件模板 (四)
Xamarin XAML语言教程构建ControlTemplate控件模板 (四) 2.在页面级别中构建控件模板 如果开发者要在页面级别中构建控件模板,首先必须将ResourceDictionary添 ...
- small test on 5.30 night T2
(题面写错了,应该是一条从b -> a 的边) 让我们设状态 (a,b,c) 表示存在一个点k,使得 dist(k,b) - dist(k,a) * 2 + 3 = c,显然这里的第三维可以压 ...
- HDOJ 5693 D Game
众所周知,度度熊喜欢的字符只有两个:B 和D. 今天,它发明了一个游戏:D游戏. 度度熊的英文并不是很高明,所以这里的D,没什么高深的含义,只是代指等差数列[(等差数列百科)](http://baik ...
- lua 脚本之高级篇 (面向对象的完全支持),有性能问题。
---------------------------------------------------------- --面向对象核心库 ------------------------------- ...
- Android UI Material Design
Material Design 中文版: http://wiki.jikexueyuan.com/project/material-design/ Material Design开发文章系列1:App ...
- JavaScript:this是什么
JavaScript:this是什么? 定义:this是包含它的函数作为方法被调用时所属的对象. 说明:这句话有点咬嘴,但一个多余的字也没有,定义非常准确,我们可以分3部分来理解它! 1.包含它的函数 ...
- 解决ThinkPHP3.2.3框架,PDO驱动类“抛出异常”不起作用的bug
项目中引进了ThinkPHP3.2.3的模型层,发现当SQL语句出错时,系统抛出的异常不是我想要的效果,打开文件 ThinkPHP\Library\Think\Db\Driver.class.php, ...
- 大湿教我写程序(2)之走向AV之路
一.大摆庆功宴 上一篇博文<大湿教我写程序(1)之菜单导航篇>中讲到了我撸码到晚上两点多,整出了一个还算是高端大气上档次的demo.半夜回到家里打算着可以好好睡上一个懒觉,到时候直接到客户 ...
- SpringMVC学习记录(七)--拦截器的使用
SpringMVC的请求如以下这样的图所看到的: 能够看出全部的请求都要通过Dispatherservlet来接收,然后通过Handlermapping来决定使用哪个控制器,再依据ViewResolv ...
- mysql 初始化报错 /usr/local/mysql/bin/mysqld:error while loading shared libraries :libaio.so.1
安装mysql在初始化的时候,出现/usr/local/mysql/bin/mysqld:error while loading shared libraries:libaio.so.1 :canno ...