题目大意:
n个人依次贴海报,每张海报都有张贴范围(li<=x<=ri);后贴的会覆盖以前的,问最后最多能看见几张。
以下解法是摘大神博客的- -,勿喷。
解法:离散化,如下面的例子(题目的样例),因为单位1是一个单位长度,将下面的
1 2 3 4 6 7 8 10
— — — — — — — —
1 2 3 4 5 6 7 8
离散化 X[1] = 1; X[2] = 2; X[3] = 3; X[4] = 4; X[5] = 6; X[7] = 8; X[8] = 10
于是将一个很大的区间映射到一个较小的区间之中了,然后再对每一张海报依次更新在宽度为1~8的墙上(用线段树),最后统计不同颜色的段数。
但是只是这样简单的离散化是错误的,
如三张海报为:1~10 1~4 6~10
离散化时 X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 6, X[ 4 ] = 10
第一张海报时:墙的1~4被染为1;
第二张海报时:墙的1~2被染为2,3~4仍为1;
第三张海报时:墙的3~4被染为3,1~2仍为2。
最终,第一张海报就显示被完全覆盖了,于是输出2,但实际上明显不是这样,正确输出为3。
新的离散方法为:在相差大于1的数间加一个数,例如在上面1 4 6 10中间加5(算法中实际上1,4之间,6,10之间都新增了数的)
X[ 1 ] = 1, X[ 2 ] = 4, X[ 3 ] = 5, X[ 4 ] = 6, X[ 5 ] = 10
这样之后,第一次是1~5被染成1;第二次1~2被染成2;第三次4~5被染成3
最终,1~2为2,3为1,4~5为3,于是输出正确结果3。
链接:http://poj.org/problem?id=2528
代码:#include <iostream>
#define N 10005
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
int x[N<<3],col[N<<4],ans;
int m,li[N],ri[N];
bool hash[N];
void PushDown(int root)
{
col[root<<1]=col[root<<1|1]=col[root];
col[root]=-1;
}
void build(int L,int R,int c,int l,int r,int root)
{
if(L<=l&&r<=R)
{
col[root]=c;
return;
}
if(col[root]!=-1) PushDown(root);
int mid=(r+l)/2;
if(mid>=L) build(L,R,c,l,mid,root<<1);
if(mid<R) build(L,R,c,mid+1,r,root<<1|1);
}
void query(int l,int r,int root)
{
if(l==r)
{
if(!hash[col[root]])
{
ans++;
hash[col[root]]=1;
}
return ;
}
if(col[root]!=-1) PushDown(root);
int mid=(r+l)>>1;
query(l,mid,root<<1);
query(mid+1,r,root<<1|1);
}
int search(int l,int r,int xx)
{
int mm;
while(l<=r)
{
mm=(l+r)>>1;
if(x[mm]==xx) return mm;
else if(x[mm]>xx) r=mm-1;
else l=mm+1;
}
return -1;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(col,-1,sizeof(col));
memset(hash,0,sizeof(hash));
int nn=0;
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&li[i],&ri[i]);
x[++nn]=li[i];
x[++nn]=ri[i];
}
sort(x+1,x+nn+1);
m=1;
for(int i=2;i<=nn;i++)
if(x[i]!=x[i-1]) x[++m]=x[i];
for(int i=m;i>1;i--)
if (x[i] - x[i-1] > 1) x[++m] = x[i] - 1;
sort(x+1,x+m+1);
for(int i=1;i<=n;i++)
{
int l=search(1,m,li[i]);
int r=search(1,m,ri[i]);
build(l,r,i,1,m,1);
}
ans=0;
query(1,m,1);
printf("%d\n",ans);
}
return 0;
}