1. 程式人生 > >poj2528 線段樹 離散化

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;
}