poj2528-Mayor's posters(线段树,区间,离散化)

来源:互联网 发布:mate10 预装软件 编辑:程序博客网 时间:2024/06/06 03:42

题目来源:http://poj.org/problem?id=2528

题意

在足够的矩形图形上贴海报,给出每张海报的左右边界,另外,海报之间相互覆盖,问,最后还能看到多少张海报。(看见一点就可以认为符合要求)

思路

线段树进行延迟标记,最后一遍递归遍历最后的节点的标记,记录下所有标记得种类数目。
用到的技巧:
离散化。
这里的离散化比较特殊,请看(借用大佬的样例):
1~10
1~3
7~10
那么按照一般的离散化结果就是:
1~3
1~2
2~3
那么结果从原来的3变成了2。。。。
这就比较尴尬了。。。那么我们可以在3和7之间插入一个数4(都行,在他俩之间就可以),简单来说,就是在去重后的数组里如果当前项减去前一项大于1,那么就在他俩之间插入一个数。
比如上面这个:(插入后结果是(我还排了个序))
1 2 3 4 7 8 10
那么三个区间就成了:
0~6
0~2
4~6
。。。完

代码

#include<map>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=20000+10;struct pp{    int x,y;} segment[maxn];int little[maxn*3];int tree[maxn<<3];bool vis[maxn*3];void updata(int l,int r,int L,int R,int rt,int flag){    if(L<=l&&R>=r)    {        tree[rt]=flag;        return;    }    int m=(l+r)/2;    if(L<=m)    {        updata(l,m,L,R,rt<<1,flag);    }    if(R>m)        updata(m+1,r,L,R,rt<<1|1,flag);}int  num=0;void dfs_tree(int rt,int l,int r){    if(l==r)    {        if(!vis[tree[rt]])        {            num++;            vis[tree[rt]]=1;        }        return;    }    int m=(l+r)/2;    if(tree[rt]>=tree[rt<<1]) tree[rt<<1]=tree[rt];    if(tree[rt]>=tree[rt<<1|1]) tree[rt<<1|1]=tree[rt];    dfs_tree(rt<<1,l,m);    dfs_tree(rt<<1|1,m+1,r);}int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n;        scanf("%d",&n);        for(int i=0; i<n; i++)        {            scanf("%d%d",&segment[i].x,&segment[i].y);            little[2*i]=segment[i].x;            little[2*i+1]=segment[i].y;        }        sort(little,little+2*n);        int m=unique(little,little+2*n)-little;        int t=m;        for(int i=1; i<t; i++)            if(little[i]-little[i-1]>1)                little[m++]=little[i-1]+1;        sort(little,little+m);        memset(tree,0,sizeof(tree));        for(int i=0; i<n; i++)        {            segment[i].x=lower_bound(little,little+m,segment[i].x)-little;            segment[i].y=lower_bound(little,little+m,segment[i].y)-little;            updata(0,m,segment[i].x,segment[i].y,1,i+1);        }        num=0;        memset(vis,0,sizeof(vis));        vis[0]=1;        dfs_tree(1,0,m);        printf("%d\n",num);    }}//尴尬的我不知道为啥tree[maxn<<2]一直RE,然后偷偷的改成<<3,过了。。。
阅读全文
0 0
原创粉丝点击