码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2015-08-25 23:57:41      阅读:500      评论:0      收藏:0      [点我收藏+]

标签:线段树   离散化   数据结构   

题目请点我
题解:
这道题与之前的题目相比重点在于一个映射的预处理,题目所给的区间达到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(线段树+离散化)

标签:线段树   离散化   数据结构   

原文地址:http://blog.csdn.net/eashion1994/article/details/47984175

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!