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 ...
随机推荐
- 【博弈论】【SG函数】Codeforces Round #188 (Div. 1) D. Game with Powers
将整个游戏可以划分成若干个互不相交的子游戏. 每个子游戏的sg值只与其中的数的个数有关.而这个数不会超过30. 于是可以预处理出这个sg值表. 然后从1到n枚举,对<=sqrt(n)的部分,用个 ...
- 【树链剖分】【dfs序】【线段树】bzoj2836 魔法树
这道题告诉我们:树链剖分的重标号就是dfs序. #include<cstdio> #include<algorithm> using namespace std; #defin ...
- 【OpenJudge9272】【DP】偶数个数字3
偶数个数字3 总时间限制: 10000ms 单个测试点时间限制: 1000ms 内存限制: 131072kB [描述] 在所有的N位数中,有多少个数中有偶数个数字3? [输入] 一行给出数字N,N&l ...
- winform treeview 绑定文件夹和文件
转载:http://www.cnblogs.com/zhbsh/archive/2011/05/26/2057733.html #region treeview 绑定文件夹和文件 /// <su ...
- [Javascript]js判断是否为undefined类型
概述 在项目获取某个元素的值会出现undefined,所以对这种情况要有特殊处理. 可通过下面的代码判断是否为undefined类型. if (typeof(reValue) == "und ...
- [功能]点击ImageView进入页面,时间响应者链实现
app点击一个按钮跳转到另外一个控制器非常常用,但是如果是点击的是UIImageView如何通过模态视图进入另外一个控制器呢?万一这个UIImageView在自定义的cell或者view里面,那该如何 ...
- 第三天 ThinkPHP手把手高速拼接站点(三)
6月1日,小雨." 梅子金黄杏子肥,麦花雪白菜花稀. 日长篱落无人过,唯有蜻蜓蛱蝶飞." 七.MVC模式 ThinkPHP的MVC开发机制例如以下: M Model层 模型 ...
- linux服务器网络配置
一.配置linux服务器的网络 手动修改配置网卡文件 先检查网卡是否正常 lspci |grep Ether 与网卡相关的TCP/IP网络配置文件位置 /etc/sysconfig/network-s ...
- java project打包生成jar包(通用)
1. 在工程目录下新建一个build.xml文件,如下图所示,注意必须是在工程目录下,而不是在工程目录的src目录里. 2.编写ant脚本,内容如下,jar文件名称(com.anllin.rup.bo ...
- python实现word2vec训练结果bin文件转txt文件
经理让我把word2vec训练后得到的bin文件转为txt文件,目前还不知道txt文件用来干什么.其实word2vec训练语料时可以选择训练处出bin文件或者txt文件,但是训练出bin文件时过程太漫 ...