poj2528 Mayor’s posters

题意:在墙上贴海报,海报可以互相覆盖,问最后可以看见几张海报

思路:这题数据范围很大,直接搞超时+超内存,需要离散化:

离散化简单的来说就是只取我们需要的值来用,比如说区间[1000,2000],[1990,2012]
我们用不到[-∞,999][1001,1989][1991,1999][2001,2011][2013,+∞]这些值,所以我只需要1000,1990,2000,2012就够了,将其分别映射到0,1,2,3,在于复杂度就大大的降下来了

所以离散化要保存所有需要用到的值,排序后,分别映射到1~n,这样复杂度就会小很多很多

而这题的难点在于每个数字其实表示的是一个单位长度(并非一个点),这样普通的离散化会造成许多错误(包括我以前的代码,poj这题数据奇弱)

例子一:1-10 1-4 5-10

例子二:1-10 1-4 6-10

普通离散化后都变成了[1,4][1,2][3,4]

线段2覆盖了[1,2],线段3覆盖了[3,4],那么线段1是否被完全覆盖掉了呢?

例子一是完全被覆盖掉了,而例子二没有被覆盖

为了解决这种缺陷,我们可以在排序后的数组上加些处理,比如说[1,2,6,10]

如果相邻数字间距大于1的话,下标位置向后延一下就行了 。。。比如说6是排名第三位的,我把它排名到第四位就好了。这个原理应该不难想出来的。

为了解决这种缺陷,我们可以在排序后的数组上加些处理,比如说[1,2,6,10]

如果相邻数字间距大于1的话,在其中加上任意一个数字,比如加成[1,2,3,6,7,10],然后再做线段树就好了.

线段树功能:update:成段替换 query:简单hash

线段树成段更新。查询的时候,实际上是二分遍历整个查询区间,每一个单位用vis来标记是否访问过。然后用D[x]来识别是否整个区间是连续的。

先不考虑离散化的问题。关于Update,我觉得本身它的Pushdown操作中携带本身题目要求的覆盖的成分,所以Pushdown是必须的。而不需要Pushup。

针对于Query操作。网上很多的题解中都没有Pushdown,这是因为本身Update的某个区间肯定和Query的某个区间是相同的,万一不同,还是需要Pushdown的,所以我写了这个操作在Query里,也是能AC的,而且我觉得是必要的。

关于离散化,由于数据范围大,查询量少。所以离散化是必要的,没什么好说的。。但是有一点,很多人忽略了完全覆盖的问题,即便是AC代码也是这样,事实上,这是因为Poj这题的数据太弱了。。。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#include <iostream> using namespace std;
#define Maxn 60005
#define lx (x<<1)
#define rx ((x<<1) | 1)
#define MID ((l + r)>>1)
struct Node
{
int val;
int id;
bool operator <(const Node &a) const
{
return val<a.val || (val == a.val && id<a.id);
}
}A[Maxn];
int D[Maxn<<2];
int vis[Maxn];
int rank[Maxn];
int t,n;
void init()
{
memset(D,0,sizeof(D));
memset(vis,0,sizeof(vis));
}
void pushDown(int x)
{
if(D[x])
{
D[lx] = D[rx] = D[x];
D[x] = 0;
}
}
int query(int L,int R,int l,int r,int x)
{
if(D[x])
{
if(!vis[D[x]]) //之前可能1张海报跨了很多区间,D[X]=d D[Y]=d 这里一次性就让 vis[d] =1 了 防止多次
{
vis[D[x]] = 1;
return 1;
}
return 0;
}
//我觉得这一步是必要的。即使对于本题没有作用,但是思路上要求我们要这么做。
//pushDown(x);
if(l == r) return 0;
int ans = 0;
if(L<=MID) ans += query(L,R,l,MID,lx);
if(MID+1<=R) ans +=query(L,R,MID+1,r,rx);
return ans;
}
void update(int d,int L,int R,int l,int r,int x)//延迟更新
{
if(L<=l && r<=R)
{
D[x] = d; //注意这里==d的原因
return; //如果存在区间更小的 大区间就要往下 相当于分割的效果
}
pushDown(x);
if(L<=MID) update(d,L,R,l,MID,lx);
if(MID+1<=R) update(d,L,R,MID+1,r,rx);
}
int main()
{
#ifndef ONLINE_JUDGE #endif
scanf(" %d",&t);
while(t--)
{
scanf(" %d",&n);
n *= 2;
for(int i=0;i<n;i++)
{
scanf(" %d",&A[i].val);
A[i].id = i;
}
sort(A,A+n);
int cnt = 1;
rank[A[0].id] = cnt;
int lastValue = A[0].val;//A[i].id存的是第几个
for(int i=1;i<n;i++)
{
if(A[i].val == lastValue) rank[A[i].id] = cnt;//rank[最小的那个值]=1 但是里面存的是之前第几个
//相邻数据如果相隔大于1,Rank向后延一位
else if(A[i].val - lastValue>1)
{
++cnt;
rank[A[i].id] = ++cnt;
lastValue = A[i].val;
}
else
{
rank[A[i].id] = ++cnt;
lastValue = A[i].val;
}
}
init();
for(int i=0;i<n/2;i++) update(i+1,rank[i<<1],rank[i<<1 | 1],1,cnt,1); // (1,rank[0],rank[1]) A[].id=0/1; 找到对应的cnt
int ans = query(1,cnt,1,cnt,1);
printf("%d\n",ans);
}
return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

线段树---poj2528 Mayor’s posters【成段替换|离散化】的更多相关文章

  1. 【线段树】Mayor's posters

    [poj2528]Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 66154   Accept ...

  2. 线段树(单点更新and成段更新)

    线段树需要的空间. 区间为1-->n 假设是一棵完全二叉树,且树高为i. 完全二叉树性质:第i层最多有2^(i-1)个结点. 那么 2^(i-1) = n;     i = log2(n)  + ...

  3. 线段树 G - Mayor's posters 小技巧

    G - Mayor's posters POJ - 2528 这个题目要倒着来写,从后面往前面贴,因为前面的有些会被后面的覆盖. 所以我们就判断这张海报的位置有没有完全被覆盖,如果完全被覆盖了就不能贴 ...

  4. (线段树)Mayor's posters --poj -- 2528

    链接: http://poj.org/problem?id=2528 覆盖问题, 要从后往前找, 如果已经被覆盖就不能再覆盖了,否则就可以覆盖 递归呀递归什么时候我才能吃透你 代码: #include ...

  5. POJ 2528.Mayor's posters-线段树(成段替换、离散数据、简单hash)

    POJ2528.Mayor's posters 这道题真的是线段数的经典的题目,因为数据很大,直接建树的话肯定不可以,所以需要将数据处理一下,没有接触离散化的时候感觉离散化这个东西相当高级,其实在不知 ...

  6. hdu1698 Just a Hook 线段树:成段替换,总区间求和

    转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 Problem ...

  7. 计蒜客 38229.Distance on the tree-1.树链剖分(边权)+可持久化线段树(区间小于等于k的数的个数)+离散化+离线处理 or 2.树上第k大(主席树)+二分+离散化+在线查询 (The Preliminary Contest for ICPC China Nanchang National Invitational 南昌邀请赛网络赛)

    Distance on the tree DSM(Data Structure Master) once learned about tree when he was preparing for NO ...

  8. poj2528 Mayor's posters(线段树之成段更新)

    Mayor's posters Time Limit: 1000MSMemory Limit: 65536K Total Submissions: 37346Accepted: 10864 Descr ...

  9. POJ2528 Mayor's posters —— 线段树染色 + 离散化

    题目链接:https://vjudge.net/problem/POJ-2528 The citizens of Bytetown, AB, could not stand that the cand ...

随机推荐

  1. 关于IScroll使用中的常见问题与解决方案

    1.在iscroll4的滚动容器范围内,点击input框.select等表单元素时没有响应这个问题原因在于iscroll需要一直监听用户的touch操作,以便灵敏的做出对应效果,所以它把其余的默认事件 ...

  2. WOT干货大放送:大数据架构发展趋势及探索实践分享

      WOT大数据处理技术分会场,PingCAP CTO黄东旭.易观智库CTO郭炜.Mob开发者服务平台技术副总监林荣波.宜信技术研发中心高级架构师王东及商助科技(99Click)顾问总监郑泉五位讲师, ...

  3. Python学习——编程语言介绍

    开发语言 高级语言:基于C/汇编等封装的语言,如Python.Java.C#.PHP.Go.ruby.C++……生成字节码让C/汇编去识别 低级语言:直接让计算机底层能识别成机器码的语言(计算机再将机 ...

  4. PTA基础编程题目集6-5求自定类型元素的最大值 (函数题)

    原题目: 本题要求实现一个函数,求N个集合元素S[]中的最大值,其中集合元素的类型为自定义的ElementType. 函数接口定义: ElementType Max( ElementType S[], ...

  5. C#基础之继承

    继承是在类之间建立一种相交的关系,使得新定义的派生类的实例可以继承已有的基类的特征并且还可以添加新的功能.以前对继承的理解仅仅限于定义,下面是我查了些资料.写了点代码的总结. 1.C#继承的特点 (1 ...

  6. CF543E Listening to Music

    题面 空间只有$64\text{MB}$!!! 题解 (据说正解是毒瘤分块套分块) 按照权值从大到小排序,对所有能够覆盖到它的区间的左端点打个标记 按照值域建一棵主席树就可以了 区间查询最大值,用$m ...

  7. [POI2011]MET-Meteors

    题面 题解 首先我们尝试暴力,那么就对每个点二分一下即可. 我们发现单独二分复杂度太高,而且有些地方很浪费,如求前缀和等. 那么我们就想,能否将它们合并在一起二分呢? 于是就有了整体二分 整体二分即可 ...

  8. Spring中的TransactionProxyFactoryBean作用及配置(转)

    问: 原文链接 http://blog.csdn.net/cpp_lzth/article/details/6551703 看AOP的时候发现spring中有个org.springframework. ...

  9. 【MYSQL命令】mysql基础命令

    1.查询MYSQL当前用户命令:select user() mysql> select user(); +------------------------+ | user() | +------ ...

  10. Python数据分析开发环境

    准备工作 下载并安装最新版本的Anaconda 下载并安装最新版本的Visual Studio Code 编辑器 Tips: 可以选择自己喜欢并且熟悉的编辑器或IDE.如:VIM.Emacs.Note ...