hihoCoder:#1079(线段树+离散化)

题目大意:给n个区间,有的区间可能覆盖掉其他区间,问没有完全被其他区间覆盖的区间有几个?区间依次给出,如果有两个区间完全一样,则视为后面的覆盖前面的。

题目分析:区间可能很长,所以要将其离散化。但离散化之后区间就变成了连续的,不再是离散的。也就是叶子由左右端点为u、u变成了左右端点为u-1、u,左右儿子有(l,mid)和(mid+1,r)变成了(l,mid)和(mid,r)。所以离散化之后要以长度为1的区间为叶子节点建立线段树,而不是以1、2、3...为叶子节点建线段树。

代码如下:

# include<iostream>
# include<cstdio>
# include<set>
# include<map>
# include<cstring>
# include<algorithm>
using namespace std;

const int N=200000;

int tr[N*4+5];
int n,m;
int lazy[N*4+5];
int x[N+5],y[N+5];
set<int>s;
map<int,int>mp;
int num[N+5];

void pushDown(int rt,int l,int r)
{
    if(lazy[rt]==-1) return ;
    lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
    tr[rt<<1]=tr[rt<<1|1]=tr[rt];
    lazy[rt]=-1;
}

void update(int rt,int l,int r,int L,int R,int val)
{
    if(L<=l&&r<=R){
        tr[rt]=val;
        lazy[rt]=val;
    }else{
        pushDown(rt,l,r);
        int mid=l+(r-l)/2;
        if(L<=mid) update(rt<<1,l,mid,L,R,val);
        if(R>mid) update(rt<<1|1,mid+1,r,L,R,val);
    }
}

void query(int rt,int l,int r)
{
    if(l==r){
        if(tr[rt]!=-1) s.insert(tr[rt]);
        return ;
    }
    if(lazy[rt]!=-1){
        s.insert(tr[rt]);
        return ;
    }
    int mid=l+(r-l)/2;
    query(rt<<1,l,mid);
    query(rt<<1|1,mid+1,r);
}

int f(int l,int r,int x)
{
    while(l<r){
        int mid=l+(r-l)/2;
        if(num[mid]<x)
            l=mid+1;
        else
            r=mid;
    }
    return l;
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        num[0]=0;
        mp.clear();
        for(int i=0;i<n;++i){
            scanf("%d%d",x+i,y+i);
            if(mp[x[i]]==0) num[++num[0]]=x[i],++mp[x[i]];
            if(mp[y[i]]==0) num[++num[0]]=y[i],++mp[y[i]];
        }
        sort(num+1,num+num[0]+1);
        memset(tr,-1,sizeof(tr));
        memset(lazy,-1,sizeof(lazy));
        for(int i=0;i<n;++i){
            int a=f(1,num[0]+1,x[i]);
            int b=f(1,num[0]+1,y[i]);
            update(1,1,num[0]-1,a,b-1,i);
        }
        s.clear();
        query(1,1,num[0]-1);
        printf("%d
",s.size());
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/20143605--pcx/p/5474672.html