zoukankan      html  css  js  c++  java
  • POJ 2528 Mayor's posters 线段树 离散化

      题目链接: http://poj.org/problem?id=2528

      题目描述: 在一个长度为maxn 的墙上贴海报, 海报按先后给出的顺序进行粘贴, 可以相互覆盖, 问最后可以露出几个海报(maxn <= 1e7)

      解题思路:一开始读错题了.....以为是覆盖的最多数.....如果是这样的话就直接统计最大值就可以了。 后来读明白题, 但是1e7数组又开不下, 所以得离散化, 但是这里又遇到一个问题

          给出下面两个简单的例子应该能体现普通离散化的缺陷:    
          例子一: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是否被完全覆盖掉了呢?
          例子一是完全被覆盖掉了,而例子二没有被覆盖                             转自http://blog.csdn.net/metalseed/article/details/8039326

        解决方法是在两个相差不为1的节点之后在插入一个值, 再做线段树, 由于这里只关心不同布段出现的次数, 所以不需要pushup函数, 直接一个全局变量配合着hash表就可以

        代码中有部分注释

      代码: 

    #include <iostream>
    #include <cstdio>
    #include <string>
    #include <vector>
    #include <map>
    #include <cstring>
    #include <iterator>
    #include <cmath>
    #include <algorithm>
    #include <stack>
    #include <deque>
    #include <map>
    
    #define lson l, m, rt<<1
    #define rson m+1, r, rt<<1|1
    typedef long long LL;
    using namespace std;
    int cases;
    const int maxn = 1e5+100;
    bool hash1[maxn];
    int li[maxn];
    int ri[maxn];
    int X[maxn*3];
    int col[maxn<<4];
    int cnt;
    
    void PushDown( int rt ) {
        if( col[rt] != -1 ) {
            col[rt<<1] = col[rt<<1|1] = col[rt];
            col[rt] = -1;
        }
    }
    
    void update( int L, int R, int c, int l, int r, int rt ) {
        if( L <= l && r <= R ) {
            col[rt] = c;
            return;
        }
        PushDown(rt);
        int m = (l + r) >> 1;
        if( L <= m ) update( L, R, c, lson );
        if( m < R ) update( L, R, c, rson );
    }
    void query( int l, int r, int rt ) {
        if( col[rt] != -1 ) {
            if( !hash1[col[rt]] ) cnt++;
            hash1[col[rt]] = true;
            return;
        }
        if( l == r ) return;
        int m = (l + r) >> 1;
        query( lson );
        query( rson );
    }
    int Bin( int key, int n, int X[] ) {   // Bin to find the value
        int l = 0;
        int r = n-1;
        while( l <= r ) {
            int m = (l + r) >> 1;
            if( X[m] == key ) return m;
            if( X[m] < key ) l = m + 1;
            else r = m-1;
        }
        return -1;
    }
    int main() {
        int t, n;
        scanf( "%d", &t );
        while( t-- ) {
            scanf( "%d", &n );
            int nn = 0;
            for( int i = 0; i < n; i++ ) {
                scanf( "%d%d", li+i, ri+i );
                X[nn++] = li[i];
                X[nn++] = ri[i];
            }
            sort( X, X+nn );
            int m = 1;
            for( int i = 1; i < nn; i++ ) { // unique
                if( X[i] != X[i-1] ) {
                    X[m++] = X[i];
                }
            }
            for( int i = m-1; i > 0; i-- ) {
                if( X[i] != X[i-1] +1 ) X[m++] = X[i-1] + 1; // deal with the drawback
            }
            sort( X, X+m );
            memset(col, -1, sizeof(col));
            for( int i = 0; i < n; i++ ) {
                int l = Bin(li[i], m, X);
                int r = Bin(ri[i], m, X);
                update( l, r, i, 0, m, 1 );
            }
            cnt = 0;
            memset( hash1, false, sizeof( hash1) );
            query(0, m, 1);
            printf( "%d
    ", cnt );
        }
        return 0;
    }
    View Code

      思考: 自己第一次做不是裸的线段树, 还是有好多好多不熟练的地方, 决定按照之前转载的那篇博客先把那里的题目刷干净, 在自己去找题做, 线段树是个硬骨头, 不好啃, 需要一些耐心, 但是只要学明白线段树, 收益无穷。 

      今晚儿再做一道DP。。。。。。

  • 相关阅读:
    long和Long的区别
    C语言的变量的内存分配
    Java蓝桥杯 算法提高 九宫格
    Java实现 蓝桥杯算法提高金明的预算方案
    Java实现 蓝桥杯 算法提高 新建Microsoft world文档
    Java实现 蓝桥杯 算法提高 快乐司机
    Java实现 蓝桥杯 算法提高 三角形
    Java实现 蓝桥杯 算法提高 三角形
    Java实现 蓝桥杯 算法提高 三角形
    Java实现 蓝桥杯 算法提高 三角形
  • 原文地址:https://www.cnblogs.com/FriskyPuppy/p/7300511.html
Copyright © 2011-2022 走看看