您的位置:首页 > 其它

poj - 2528 Mayor's posters(线段树+离散化)

2015-08-10 17:18 232 查看
题意:在墙上贴海报,海报之间可以互相覆盖,问最后可以看见几张海报.

思路:这题数据范围很大,直接搞容易超时+超内存,需要离散化.

离散化简单来说就是只取我们需要用到的值来用,比如说区间[1000,2000],[1990,2012]

我们用不到[-inf,999][1001,1989],[1991,1999],[2001,2011][2013,+inf]这些值,

所以只需要1000,1990,2000,2012就够了,将其分别映射到0,1,2,3复杂度就会降下来.

所以离散化就是保存所有需要用到的值,排序后,分别映射到1-n,就可以降低复杂度.

但是这题每个数字其实表示一个单位长度(并非一个点),普通离散化会造成许多错误.

比如:

1-10 1-4 5-10
1-10 1-4 6-10

离散化后都是[1,4][1,2][3,4]
为了解决这种缺陷,我们可以在排序后的数组上加些处理,比如说[1,2,6,10]
如果相邻数字间距大于1的话,在其中加上任意一个数字,比如加成[1,2,3,6,7,10],然后再做线段树就好了.
线段树功能:update:成段替换 query:简单hash

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

const int maxn = 11111;
bool hash[maxn];
int li[maxn],ri[maxn];
int x[maxn*3];
int col[maxn<<4];
int cnt;

void pushDown(int rt)
{
if(col[rt]!=-1)
{
col[rt<<1]=col[rt<<1|1]=col[rt];
col[rt]=-1;
}
}

void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
col[rt]=c;
return;
}
pushDown(rt);
int m=(l+r)>>1;
if(L<=m) update(L,R,c,lson);
if(m<R) update(L,R,c,rson);
}

void query(int l,int r,int rt)
{
if(col[rt]!=-1)
{
if(!hash[col[rt]]) cnt++;
hash[col[rt]]=true;
return;
}
if(l==r) return;
int m=(l+r)>>1;
query(lson);
query(rson);
}

int Bin(int key,int n,int x[])
{
int l=0,r=n-1;
while(l<=r)
{
int m=(l+r)>>1;
if(x[m]==key) return m;
if(x[m]<key) l=m+1;
else r=m-1;
}
return -1;
}

int main()
{
//freopen("a.txt","r",stdin);
int t,n;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int nn=0;
for(int i=0;i<n;i++)
{
scanf("%d%d",&li[i],&ri[i]);
x[nn++]=li[i];
x[nn++]=ri[i];
}
sort(x,x+nn);
int m=1;
for(int i=1;i<nn;i++) //去掉重复的
{
if(x[i]!=x[i-1]) x[m++]=x[i];
}
for(int i=m-1;i>0;i--) //如果间距大于1就插入任意一个数
{
if(x[i]!=x[i-1]+1) x[m++]=x[i-1]+1;
}
sort(x,x+m);
memset(col,-1,sizeof(col));
for(int i=0;i<n;i++) //二分查找左右边界在x中的位置
{
int l=Bin(li[i],m,x);
int r=Bin(ri[i],m,x);
update(l,r,i,0,m,1);//用第i种颜色更新
}
cnt=0;
memset(hash,0,sizeof(hash));
query(0,m,1);
printf("%d\n",cnt);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: