【POJ 2528】Mayor’s posters(线段树+离散化)

题目

给定每张海报的覆盖区间,按顺序覆盖后,最后有几张海报没有被其他海报完全覆盖。
离散化处理完区间端点,排序后再给相差大于1的相邻端点之间再加一个点,再排序。
线段树,tree[i]表示节点i对应区间是哪张海报,如果是-1代表对应区间不是一张海报(0或多张)。
每贴一张海报,就用二分查找出覆盖的起点和终点对应的离散后的下标,然后更新区间。
线段树的区间更新可以加上懒惰标记(或延迟标记,但是这题可以不用另外标记。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 10005
using namespace std;
int m,li[N],ri[N];
int x[N<<3],tree[N<<4],ans;
bool hash[N];
void PushDown(int node){
    tree[node<<1]=tree[node<<1|1]=tree[node];
    tree[node]=-1;
}
void Update(int v,int l,int r,int node,int L,int R){
    if(L>r||R<l)return;
    if(L<=l&&r<=R){
        tree[node]=v;
        return;
    }
 
    if(tree[node]!=-1) PushDown(node);
    int m=l+r>>1;
    Update(v,l,m,node<<1,L,R);
    Update(v,m+1,r,node<<1|1,L,R);
}
void query(int l,int r,int node){
    if(l==r){
        if(tree[node]!=-1&&!hash[tree[node]]){
            ans++;
            hash[tree[node]]=1;
        }
        return;
    }
    if(tree[node]!=-1)PushDown(node);
    int m=l+r>>1;
    query(l,m,node<<1);
    query(m+1,r,node<<1|1);
}
int main(){
    freopen("in.txt","r",stdin);
    int t,n,i;
    scanf("%d",&t);
    while(t--){
        memset(tree,-1,sizeof tree);
        memset(hash,0,sizeof hash);
        int k=0;
        scanf("%d",&n);
        for(i=1;i<=n;i++){
            scanf("%d%d",&li[i],&ri[i]);
            x[++k]=li[i];
            x[++k]=ri[i];
        }
        sort(x+1,x+k+1);
        m=1;
        for(i=2;i<=k;i++){
            if(x[i]!=x[i-1])x[++m]=x[i];
        }
        for(i=m;i>1;i--){
            if(x[i]-x[i-1]>1)x[++m]=x[i]-1;
        }
        sort(x+1,x+m+1);
        for(i=1;i<=n;i++){
            int l=lower_bound(x+1,x+m,li[i])-x;
            int r=lower_bound(x+1,x+m,ri[i])-x;
            Update(i,1,m,1,l,r);
        }
        ans=0;
        query(1,m,1);
        printf("%d
",ans);
    }
}

  

原文地址:https://www.cnblogs.com/flipped/p/5693739.html