• hihoCoder #1079 : 离散化


    #1079 : 离散化

    时间限制:10000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    小Hi和小Ho在回国之后,重新过起了朝7晚5的学生生活,当然了,他们还是在一直学习着各种算法~

    这天小Hi和小Ho所在的学校举办社团文化节,各大社团都在宣传栏上贴起了海报,但是贴来贴去,有些海报就会被其他社团的海报所遮挡住。看到这个场景,小Hi便产生了这样的一个疑问——最后到底能有几张海报还能被看见呢?

    于是小Ho肩负起了解决这个问题的责任:因为宣传栏和海报的高度都是一样的,所以宣传栏可以被视作长度为L的一段区间,且有N张海报按照顺序依次贴在了宣传栏上,其中第i张海报贴住的范围可以用一段区间[a_i, b_i]表示,其中a_i, b_i均为属于[0, L]的整数,而一张海报能被看到当且仅当存在长度大于0的一部分没有被后来贴的海报所遮挡住。那么问题就来了:究竟有几张海报能被看到呢?

    提示一:正确的认识信息量

    提示二:小Hi大讲堂之线段树的节点意义

    输入

    每个测试点(输入文件)有且仅有一组测试数据。

    每组测试数据的第1行为两个整数N和L,分别表示总共贴上的海报数量和宣传栏的宽度。

    每组测试数据的第2-N+1行,按照贴上去的先后顺序,每行描述一张海报,其中第i+1行为两个整数a_i, b_i,表示第i张海报所贴的区间为[a_i, b_i]。

    对于100%的数据,满足N<=10^5,L<=10^9,0<=a_i<b_i<=L。

    输出

    对于每组测试数据,输出一个整数Ans,表示总共有多少张海报能被看到。

    样例输入
    5 10
    4 10
    0 2
    1 6
    5 9
    3 4
    样例输出
    5
    题目链接:http://hihocoder.com/problemset/problem/1079

    题意:n张海报按顺序粘贴,每张海报粘贴的位置为[ai,bi],问最后在墙上[0,L]能看到多少张海报。
    思路:因为n只有105,而粘贴区间却有109。首先离散化海报的张贴区间。然后利用线段树区间更新来更新粘贴区间。注意:
    由于海报的粘贴区间是非离散化的数据,即是连续的。所以[l,r]必须分解成[l,mid][mid,r]。这是与离散型数据的区别,
    离散型数据的区间[l,r]分解成[l,mid][mid+1,r]。
    例如这样一种数据:
    3 4
    1 4
    1 2
    3 4
    如果按照离散型数据来二分区间的话,最后只能是有2张海报。1,2是一张,3,4是第二张,并没有考虑2~3的情况。
    按照连续性的数据来二分的花,就可以是1~2,2~3,3~4。
    其实按照离散型数据来二分区间也是可以的,只需要把[ai,bi]变成[ai*2,bi*2]就可以了。
    TL中unique的函数 unique的功能是去除相邻的重复元素(只保留一个),不是真正把重复的元素删除,其实是,该函数把重复的元素一到后面去了,然后依然保存到了原数组中,然后返回去重后最后一个元素的地址,因为unique去除的是相邻的重复元素,所以一般用之前都会要排一下序。
    代码:
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int MAXN=1e6+100;
    int l[MAXN],r[MAXN],c[2*MAXN];
    int lazy[MAXN];
    int date[MAXN];
    int compress(int n)
    {
        memcpy(c,l,sizeof(l));
        memcpy(c+n,r,sizeof(r));
        sort(c,c+2*n);
        int size=unique(c,c+2*n)-c;
        for(int i=0; i<n; i++)
        {
            l[i]=lower_bound(c,c+size,l[i])-c+1;
            r[i]=lower_bound(c,c+size,r[i])-c+1;
            l[i]*=2;
            r[i]*=2;
        }
        return size;
    }
    void pushdown(int l,int r,int pos)
    {
        if(lazy[pos]==0) return;
        int mid=(l+r)<<1;
        lazy[pos<<1]=lazy[pos];
        lazy[pos<<1|1]=lazy[pos];
        lazy[pos]=0;
    }
    void update(int L,int R,int i,int l,int r,int pos)
    {
        if(L<=l&&r<=R)
        {
            lazy[pos]=i;
            return;
        }
        pushdown(l,r,pos);
        int mid=(l+r)>>1;
        if(L<=mid) update(L,R,i,l,mid,pos<<1);
        if(R>mid) update(L,R,i,mid+1,r,pos<<1|1);
    }
    void query(int l,int r,int pos)
    {
        if(l==r)
        {
            date[l]=lazy[pos];
            return;
        }
        pushdown(l,r,pos);
        int mid=(l+r)>>1;
        query(l,mid,pos<<1);
        query(mid+1,r,pos<<1|1);
    }
    int main()
    {
        int i,n,L;
        while(~scanf("%d%d",&n,&L))
        {
            memset(lazy,0,sizeof(lazy));
            memset(c,0,sizeof(lazy));
            for(i=0; i<n; i++)
                scanf("%d%d",&l[i],&r[i]);
            L=compress(n)*2;
            for(i=0; i<n; i++)
            {
                if(l[i]==r[i]) continue;
                update(l[i],r[i],i+1,1,L,1);
            }
            query(1,L,1);
            sort(date,date+2*L+1);
            int ans=unique(date,date+2*L+1)-(date+1);
            cout<<ans<<endl;
        }
        return 0;
    }
    离散化+线段树区间更新
    I am a slow walker,but I never walk backwards.
  • 相关阅读:
    201671010456-张琼 实验三作业互评与改进
    阅读《构建之法》后的相关问题
    个人作业-软件工程实践总结
    团队作业第二次—项目选题报告
    结对第二次—文献摘要热词统计及进阶需求
    结对第一次—原型设计(文献摘要热词统计)
    第一次作业-准备篇
    个人作业——软件工程实践总结作业
    团队作业第二次—项目选题报告
    结对第二次—文献摘要热词统计及进阶需求
  • 原文地址:https://www.cnblogs.com/GeekZRF/p/5974410.html
Copyright © 2020-2023  润新知