poj 2528——Mayor's posters

来源:互联网 发布:专业八级 知乎 编辑:程序博客网 时间:2024/06/05 15:18

题意:在一面墙上贴海报,给出每张海报占的格子范围,求最后可以看到几张海报
思路:线段树,但是各自的范围是1~10000000。如果直接用线段树表示这么大范围肯定不够。但是海报最多就10000张,一个海报就两边。将出现过的边进行离散化,使需要的空间大大缩小
样例中的线段树大概长这个样子
样例中的线段树大概长这个样子
代码如下:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int C[80005];int ans;bool flag[10005];int sl[10005];int sr[10005];int rec[20005];int yl,yr;int v;void update(int o,int l,int r){    if(l==r){        C[o]=v;        return;    } else if(rec[l]>=yl&&rec[r]<=yr){        C[o]=v;        return;    } else {        int lc=o*2;        int rc=o*2+1;        int mid=l+(r-l)/2;        if(C[o]>=0){            C[lc]=C[o];            C[rc]=C[o];            C[o]=-1;        }        if(yl<=rec[mid])update(lc,l,mid);        if(yr>=rec[mid+1])update(rc,mid+1,r);        return;    }}void dfs(int o,int l,int r){    if(C[o]>0||l==r){        if(!flag[C[o]]){            flag[C[o]]=1;            ans++;        }        return;    } else if(C[o]==0){        return;    } else {        int mid=l+(r-l)/2;        dfs(o*2,l,mid);        dfs(o*2+1,mid+1,r);    }}int main(){//    freopen("data.txt","r",stdin);    int T;    scanf("%d",&T);    while(T--){        int n;        scanf("%d",&n);        int tot=0;        for(int i=0;i<n;++i){            scanf("%d%d",&sl[i],&sr[i]);            rec[tot++]=sl[i];            rec[tot++]=sr[i];        }        sort(rec,rec+tot);        tot=unique(rec,rec+tot)-rec;        memset(C,0,sizeof(C));        memset(flag,0,sizeof(flag));        for(int i=0;i<n;++i){            yl=sl[i];            yr=sr[i];            v=i+1;            update(1,0,tot-1);        }        ans=0;        dfs(1,0,tot-1);        printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击