重叠的装饰

重叠的装饰

http://www.nowcoder.com/questionTerminal/a502e49967b44036918d93ff43be1930

题目难度:四星
考察点:线段树、区间覆盖、离散化

方法:线段树、区间覆盖

1.分析:

这道题是一个线段树区间覆盖类型的题目,通过题目我们知道,在贴海报的过程中,后面贴的海报会影响前面的海报,即前面的海报会被覆盖。所以这其实就是一个区间的更新,即来一个区间[l,r],我们对其进行update。所需要的知识就是线段数的区间更新。这一类题目也可以理解为是线段的互相覆盖,在更新过程中,动态的获取线段的并或者是区间的个数等等信息。那么在这里说一下怎么进行的区间覆盖,对于第i个区间[l,r]来说,相当于是利用i来表示覆盖的海报,所以就是相当于对[l,r]进行覆盖,即即如果满足条件的话 lazy[root] = i,进行lazy标记,所谓的lazy标记就是指在递归的过程中,如果当前区间被需要修改的区间完全覆盖,那么就要停止递归,并且在上面做一个标记。当我们套完线段树lazy区间修改模板时,发现竟然段错误了。这是为什么呢?这是由于输入的区间太大,所以不能用线段树来完全的表示,如果想用线段树来完全的表示就会MLE,所以怎么办呢?
这里介绍一个神奇的算法 离散化,是一个可以节省空间的神奇算法,离散化是对一堆元素进行操作,通过改变他们的大小,但不改变他们的大小关系来达到节省空间,减低时空复杂度的。举个例子:
现在有一个数组{4,8,10,20},我们可以计算用一个下标为{1, 2, 3, 4}的数组来表示,我们可以用一个更小的数来表达这种大小的关系。
比如说现在有一个数组{4,8,10,6},下标为{1, 2, 3, 4},首先对其进行排序得到:
数组值: 4 6 8 10
下标值: 1 4 2 3

经过离散化之后得到:
数组值: 4 6 8 10
下标值: 1 4 2 3
离散化: 1 2 3 4

在将其转到原序列之后:
数组值:     4 8 10 6
离散化后:  1 4 2 3
其实在这道题中,我们就可以采用STL的方法来进行离散化,将所有的区间的左右端点放在一个数组中,然后排序去重,最后在进行lower_bound找到对应的端点所在的下标即可,具体可详见代码。


算法步骤:
(1). 输入n和相应的n个区间,
(2). 将得到的区间排序去重,进行离散化
(3). 构造线段树,进行区间覆盖
(4). 输出结果。

2.复杂度分析: 

时间复杂度:O(nlog(n)) 
空间复杂度:O(n)

3.代码: 

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6+5;
int lazy[MAXN*3];
bool book[MAXN*3];
void pushdown(int root){
    if(lazy[root] != -1){
        lazy[root<<1] = lazy[root];
        lazy[root<<1|1] = lazy[root];
        lazy[root] = -1;
    }
}
void update(int L, int R, int flag, int l, int r, int root){
    if(L<=l && R>=r){
        lazy[root] = flag;
        return;
    }
    pushdown(root);
    int mid = (l + r)>>1;
    if(L <= mid) update(L,R,flag,l,mid,root<<1);
    if(R > mid) update(L,R,flag,mid+1,r,root<<1|1);
}
struct Node {
    int x, y;
    Node(){}
    Node(int xx, int yy) {x = xx, y = yy;}
}a[MAXN];
int query(int l, int r, int root){
    if(lazy[root] != -1){
        if(book[lazy[root]]) return 0;
        book[lazy[root]] = true;
        return 1;
    }
    if(l == r) return 0;
    int mid = (l + r)>>1, ans = 0;
    ans += query(l,mid,root<<1);
    ans += query(mid+1,r,root<<1|1);
    return ans;
}
int main(){
    memset(lazy, -1, sizeof(lazy));
    int n; cin>>n;
    vector<int> vec;
    for(int i=0; i<n; i++) {
        int x, y; cin>>x>>y;
        a[i] = Node(x, y);
        vec.push_back(x);
        vec.push_back(y);
    }
    sort(vec.begin(), vec.end());
    vec.erase(unique(vec.begin(), vec.end()), vec.end());
    for(int i=1; i<=n; i++) {
        int l = lower_bound(vec.begin(), vec.end(), a[i-1].x)-vec.begin()+1;
        int r = lower_bound(vec.begin(), vec.end(), a[i-1].y)-vec.begin()+1;
        update(l, r, i, 1, 3*n,1);
    }
    cout<<query(1, 3*n, 1);
    return 0;
}

全部评论

相关推荐

不愿透露姓名的神秘牛友
11-29 12:19
点赞 评论 收藏
分享
qz鹿:*** 祝他毕业就失业
点赞 评论 收藏
分享
死在JAVA的王小美:哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈,我也是,让我免了一轮,但是硬气拒绝了
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务