您的位置:首页 > 其它

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

2017-11-07 20:14 531 查看

题目来源: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,过了。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: