zoukankan      html  css  js  c++  java
  • 线段树线段覆盖(离散化+区间覆盖)

    n(n<=10000) 个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000) 。求出最后还能看见多少张海报。

    Input

           第一行: 样例个数T
           第二行: 贴海报的人n
           第三行: 每个人贴海报的范围
            接下来n行: 每个人贴海报的范围

    Output

    对于每一个输入,输出最后可以看到的海报张数。下面这个图是样例解释



    Sample Input

    1
    5
    1 4
    2 6
    8 10
    3 4
    7 10
    

    Sample Output

    4

    这个题如果你用普通的离散化,是错的

    如三张海报为:1~10 1~4 6~10

    离散化时 X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 6, X[ 4 ] = 10
    第一张海报时:墙的1~4被染为1;
    第二张海报时:墙的1~2被染为2,3~4仍为1;
    第三张海报时:墙的3~4被染为3,1~2仍为2。
    最终,第一张海报就显示被完全覆盖了,于是输出2,但实际上明显不是这样,正确输出为3。

    新的离散方法为:在相差大于1的数间加一个数,例如在上面1 4 6 10中间加5(算法中实际上1,4之间,6,10之间都新增了数的)

    X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 5, X[ 4 ] = 6, X[ 5 ] = 10

    这样之后,第一次是1~5被染成1;第二次1~2被染成2;第三次4~5被染成3

    最终,1~2为2,3为1,4~5为3,于是输出正确结果3。

            for(int i=1;i<=n;i++){
                scanf("%d%d",&li[i],&ri[i]);
                lsh[++cnt]=li[i];
                lsh[++cnt]=ri[i];
            }    
            sort(lsh+1,lsh+cnt+1);
            int mm=unique(lsh+1,lsh+cnt+1)-(lsh+1);
            int nn=mm;
            for(int i=2;i<=nn;i++){
                if(lsh[i]-lsh[i-1]>1){
                    lsh[++mm]=lsh[i-1]+1;
                }
            }
            sort(lsh+1,lsh+mm+1);

    离散化之后就是线段树区间修改,和单点查询

    建树修改+查询
         build(1,1,mm);
            for(int i=1;i<=n;i++){
                int x=lower_bound(lsh+1,lsh+mm+1,li[i])-lsh;
                int y=lower_bound(lsh+1,lsh+mm+1,ri[i])-lsh;
                update(1,x,y,i);
            } 
            for(int i=1;i<=mm;i++){
                int p=query(1,i);
                vis[p]++;
            }
            int ans=0;
            for(int i=1;i<=n;i++){
                if(vis[i]){
                    ans++;
                }
            } 
            cout<<ans<<endl;
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    /*
    3
    3 
    1 10
    1 4
    6 10
    */
    const int maxn=1e6+100;  
    int lsh[maxn];
    int li[maxn],ri[maxn];
    int vis[maxn];
    struct node{
        int l,r;
        int lazy;
    }t[maxn];
    int n;
    int cnt=0;
    void build(int p,int l,int r){
        t[p].l=l;
        t[p].r=r;
        t[p].lazy=0; 
        if(l==r){
            t[p].lazy=0;
            return ;
        }
        int mid=(t[p].l+t[p].r)/2; 
        build(p*2,l,mid);
        build(2*p+1,mid+1,r);
    }
    void upsh(int p){
        t[2*p].lazy=t[p].lazy;
        t[2*p+1].lazy=t[p].lazy;
        t[p].lazy=0;
    }
    void update(int p,int l,int r,int x){
        if(t[p].l>=l&&t[p].r<=r){
            t[p].lazy=x;
            return ;
        }
        if(t[p].lazy){
            upsh(p);
        }
        int mid=(t[p].l+t[p].r)/2;
        if(l<=mid){
            update(2*p,l,r,x);
        }
        if(r>mid){
            update(2*p+1,l,r,x);
        }
    } 
    int query(int p,int x){
        if(t[p].l==t[p].r){
            return t[p].lazy;
        }
        if(t[p].lazy){
            upsh(p);
        }
        int mid=(t[p].l+t[p].r)/2; 
        if(x<=mid){
            return query(2*p,x);
        }
        else{
            return query(2*p+1,x);
        }
    }
    int main(){
        int t;
        cin>>t;
        while(t--){
            cin>>n;
            memset(vis,0,sizeof(vis)); 
            cnt=0;
            for(int i=1;i<=n;i++){
                scanf("%d%d",&li[i],&ri[i]);
                lsh[++cnt]=li[i];
                lsh[++cnt]=ri[i];
            }    
            sort(lsh+1,lsh+cnt+1);
            int mm=unique(lsh+1,lsh+cnt+1)-(lsh+1);
            int nn=mm;
            for(int i=2;i<=nn;i++){
                if(lsh[i]-lsh[i-1]>1){
                    lsh[++mm]=lsh[i-1]+1;
                }
            }
            sort(lsh+1,lsh+mm+1);
            build(1,1,mm);
            for(int i=1;i<=n;i++){
                int x=lower_bound(lsh+1,lsh+mm+1,li[i])-lsh;
                int y=lower_bound(lsh+1,lsh+mm+1,ri[i])-lsh;
                update(1,x,y,i);
            } 
            for(int i=1;i<=mm;i++){
                int p=query(1,i);
                vis[p]++;
            }
            int ans=0;
            for(int i=1;i<=n;i++){
                if(vis[i]){
                    ans++;
                }
            } 
            cout<<ans<<endl;
        }
    }
  • 相关阅读:
    DAS存储未死,再次欲获重生
    Minimum edit distance(levenshtein distance)(最小编辑距离)初探
    AC自己主动机
    手动脱UPX 壳实战
    edge中断分析
    ubuntu默认的Python版本号修改
    Linux 下 pushd,popd,cd- 用法
    目标检测算法的历史及分类
    openjtag 的硬件连接踩坑历程
    ubuntu 16.04 python版本切换(python2和python3)
  • 原文地址:https://www.cnblogs.com/lipu123/p/14490821.html
Copyright © 2011-2022 走看看