如题:http://poj.org/problem?id=2528
在墙上贴一堆海报,一张海报可以覆盖已经贴上的海报,求贴完湖还可以见到的海报的数量
这一题墙的长度给的范围太大,直接用线段树分区间肯定超时,超内存,必须离散化。海报最多10000张。用结构体poster【i】.coord记录海报的坐标。然后排序,去掉重复,并一次编号.这个编号就是离散化后的结果.然后对左右编号区间贴海报(线段树节点更新)。
#include<iostream>
using namespace std;
#define N 10005 //海报数量
int result;
int l[N];
int r[N];
bool mark[N];
struct line
{
int kind; //kind表示贴的第几张海报,贴完后,当kind=0,代表者一个区间被一张以上的海报贴满,这个区间可能看见的海报已经被更新到子节点。
int left,right;
}lines[10*N];
struct item
{
int coord; // 海报左,右的坐标
int id;
}poster[2*N];
int cmp(const void * a,const void * b) //升序排序
{
return ((item *)a)->coord-((item *)b)->coord;
}
void build(int s,int t,int node)
{
lines[node].left=s;
lines[node].right=t;
if(s==t) return;
int mid=(lines[node].left+lines[node].right)/2;
build(s,mid,node*2);
build(mid+1,t,node*2+1);
}
void update(int s,int t,int node,int cover)
{
if(lines[node].left==s&&lines[node].right==t)
{
lines[node].kind=cover;
return;
}
if(lines[node].kind!=0&&lines[node].kind!=cover)
{
lines[node*2].kind=lines[node*2+1].kind=lines[node].kind;
lines[node].kind=0; //这个区间被不止一个海报完全覆盖
}
int mid=(lines[node].left+lines[node].right)/2;
if(t<=mid)
update(s,t,node*2,cover);
else if(s>mid)
update(s,t,node*2+1,cover);
else
{
update(s,mid,node*2,cover);
update(mid+1,t,node*2+1,cover);
}
}
void cal(int node)
{
if(lines[node].kind!=0)
{
if(mark[lines[node].kind]==false)
{
mark[lines[node].kind]=true;
result++;
}
}
else
{
cal(node*2);
cal(node*2+1);
}
}
int main()
{
int t,n,i,j;
struct item *templ,*tempr,tl,tr;
scanf("%d",&t);
while(t--)
{
memset(lines,0,sizeof(lines));
memset(poster,0,sizeof(poster));
memset(mark,false,sizeof(mark));
scanf("%d",&n);
for(i=j=1;i<=n;i++)
{
scanf("%d %d",&l[i],&r[i]);
poster[j++].coord=l[i];
poster[j++].coord=r[i];
}
//准备离散
qsort(poster+1,n*2,sizeof(item),cmp);
for(i=j=1;i<=2*n;i++,j++)
{
poster[j].coord=poster[i].coord;
poster[j].id=j;
while(poster[i].coord==poster[i+1].coord)
i++;
}
build(1,j-1,1);
for(int i=1;i<=n;i++)
{
tl.coord=l[i];
tr.coord=r[i];
templ=(item *)bsearch(&tl,poster+1,j,sizeof(item),cmp);
tempr=(item *)bsearch(&tr,poster+1,j,sizeof(item),cmp);
update(templ->id,tempr->id,1,i); //i当前第i张海报
}
result=0;
cal(1);
printf("%d\n",result);
}
return 0;
}