poj2528 線段樹 離散化
在牆上貼一堆海報,一張海報可以覆蓋已經貼上的海報,求貼完湖還可以見到的海報的數量
這一題牆的長度給的範圍太大,直接用線段樹分割槽間肯定超時,超記憶體,必須離散化。海報最多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;
}