POJ_2528 Mayor's poster(线段树+离散化)

题目请点我

题解:

这道题与之前的题目相比重点在于一个映射的预处理,题目所给的区间达到10000000,而最多只有10000个点,如果直接建树的话太过于空旷。把这些区间的左右节点一一对应,最多有4×10000个点,远小于之前的10000000,而且区间之间的对应关系也不会改变。

举个例子:

区间:[2,6],[4,8],[6,10]

我们进行下面对应:

2 4 6 8 10

1 2 3 4 5

则原区间变为[1,3],[2,4],[3,5]。可以发现它们之间的覆盖关系并没有改变,但是却紧凑了很多。

但是注意对应后,应该有一个去重的操作,防止出错。

还有一点去需要注意,区间的对应稍不注意会出现颜色丢失的情况,如下:

[1,10],–[1,4],–[6,10]

当我们手工模拟会发现,我们只是对1,4,6,10,进行了对应,即1,2,3,4,原集合中的4,6被视为了相邻元素,所以5处的颜色丢失,最终得到了错误的结果。

为了防止发生这种情况我们进行插值,在两个不相邻的节点间插入无关值,但是能有效的避免这种情况。

数组范围分析,10000个区间对应最多20000个节点,再进行插值后得到最多40000+个节点,对应segTree数组达到4×40000+。

而线段树部分实现起来就比较简单了,lazy标记一下,最后统计仍可见的不同颜色就可以了。

参考博客

代码实现:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define MAX 20010
#define LCHILD root<<1,l,mid
#define RCHILD root<<1|1,mid+1,r
#define MID(x,y) (x+y)>>1

using namespace std;

int T;
int N;
int mm[MAX<<2];
int show[MAX<<3];
int L[MAX],R[MAX];
int segTree[MAX<<3];
void pushdown(int root);
int query(int root,int l,int r,int a,int b);
void update(int root,int l,int r,int a,int b,int flag);
int main(){
    scanf("%d",&T);
    while( T-- ){
        scanf("%d",&N);
        int pos = 1;
        int tmp = 2;
        //注意show[0]要提前标记为1
        memset(segTree,0,sizeof(segTree));
        memset(show,0,sizeof(show));show[0] = 1;
        for( int i = 1; i <= N; i++ ){
            scanf("%d%d",&L[i],&R[i]);
            mm[pos++] = L[i];
            mm[pos++] = R[i];
        }
        //去重操作
        sort(mm+1,mm+pos);
        for( int i = 2; i < pos; i++ ){
            if( mm[i] != mm[i-1] ){
                mm[tmp++] = mm[i];
            }
        }
        //插值
        pos = tmp;
        for( int i = pos-1; i > 1; i-- ){
            if( mm[i] != mm[i-1]+1 ){
                mm[pos++] = mm[i-1]+1;
            }
        }
        sort(mm+1,mm+pos);
        //lowe_bound找到a,b位置
        for( int i = 1; i <= N; i++ ){
            int a,b;
            a = lower_bound(mm+1,mm+pos,L[i])-mm;
            b = lower_bound(mm+1,mm+pos,R[i])-mm;
            update(1,1,pos-1,a,b,i);
        }
        int res = query(1,1,pos-1,1,pos-1);
        printf("%d\n",res);
    }
    return 0;
}

void update(int root,int l,int r,int a,int b,int flag){
    if( a > r || b < l ){
        return ;
    }
    if( a <= l && r <= b ){
        segTree[root] = flag;
        return ;
    }
    if( segTree[root] != 0 ){
        pushdown(root);
    }
    int mid = MID(l,r);
    update(LCHILD,a,b,flag);
    update(RCHILD,a,b,flag);
    return ;
}

int query(int root,int l,int r,int a,int b){
    if( a > r || b < l ){
        return 0;
    }
    //该区间属于同一种颜色,show数组标记是否已被统计
    if( segTree[root]!= 0 ){
        if( show[segTree[root]] != 1 ){
            show[segTree[root]] = 1;
            return 1;
        }
        return 0;
    }
    //未标色的叶子节点
    if( l == r ){
        return 0;
    }
    int mid = MID(l,r);
    return query(LCHILD,a,b)+query(RCHILD,a,b);
}

void pushdown(int root){
    segTree[root<<1] = segTree[root];
    segTree[root<<1|1] = segTree[root];
    segTree[root] = 0;
    return ;
}

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

POJ_2528 Mayor's poster(线段树+离散化)

时间: 2024-11-08 12:51:48

POJ_2528 Mayor's poster(线段树+离散化)的相关文章

Poj 2528 Mayor&#39;s posters (线段树+离散化)

题目连接: http://poj.org/problem?id=2528 题目大意: 有10000000块瓷砖,n张海报需要贴在墙上,每张海报所占的宽度和瓷砖宽度一样,长度是瓷砖长度的整数倍,问按照所给海报顺序向瓷砖上贴海报,最后有几张海报是可见的? 解题思路: 因为瓷砖块数和海报张数多,首选线段树,如果按照常规的建树方式,把瓷砖当做数的节点,肯定会MTL......... 所以我们可以用海报的起点和终点当做树的节点,这样树的节点才有20000个,但是这样建树的话,求海报覆盖了那些节点会很复杂,

【线段树+离散化】POJ2528 Mayor&#39;s posters

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 64939   Accepted: 18770 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post

【POJ】 2528 - Mayor&#39;s posters 【线段树+离散化】

题目: Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 47228   Accepted: 13719 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral

D - Mayor&#39;s posters (线段树+离散化处理) POJ 2528

D - Mayor's posters Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2528 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing

poj 2528 Mayor&#39;s posters 【线段树 + 离散化】

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 50643   Accepted: 14675 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post

poj-----(2528)Mayor&#39;s posters(线段树区间更新及区间统计+离散化)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 43507   Accepted: 12693 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post

POJ - 2528 Mayor&#39;s posters (线段树+离散化)

Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally decided to build an electoral wall for

poj 2528 Mayor&#39;s posters(线段树 离散化 区间更新 贴海报)

     这个题目本来对大神来说可能是水题, 对我就不行了,昨晚非折腾到下半夜一点 搞定, 并且可以总结出 ,只有把问题想清楚,或着看人家解题报告自己把问题和代码思路 搞清楚,才能谈的上调bug,否则根本就不知道错在哪儿.说说这个题目的理解,他是如何转化为线段树问题的呢?我们知道线段树有一个区间更新的东西,每张海报的宽度不就是一个区间么?那么我们可以用一棵树中的部分结点 来表示整张海报的可视部分,也就是说每个结点只允许表示一张完整的或着不完整的海报(好几个结点才可以表示成完整的一张海报),那么如

poj2528 Mayor&#39;s posters(线段树+离散化)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 42808   Accepted: 12481 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post