poj2528_線段樹+離散化

題目描述:

   幾張海報有不同的覆蓋範圍,按先後順序鋪蓋上去,看最終在頂層能看到多少張不同的海報。

 

解題思路:

   線段樹——還是建樹+修改+查詢的基本操作。不過費了一天啊。。。有幾個需要注意的地方,會容易出現MLE,RE或者TLE的。

   首先是線段樹標記問題,只標記完全覆蓋的區間的tab,其餘置空以便最後search求出值,目前自己用過的企另外一種標記方式會TLE;然後就是最重要的離散化問題,一開始沒有離散化,用3*M的樹大小都RE,需要開到4*M,但是開到那個地步又會MLE。而現在算一算,其實只開一個M大小的樹就已經超過65535K了。所以必須要進行離散化,即其實這裏面有些區間段完全可以用一個單位區間段來表示,即需要對輸入的數排序去重後,把區間縮減。這樣的話,我們看到總共就輸入10000個線段,最多20000個區間段,這樣的線段樹規模比原先的一千萬就小了很多。

 

代碼:

#include
#include

typedef struct {
   int l,r;
   int tab;
}CH;

CH segTree[70000];
int n, num, flag[20001], tmp_array[20002], array[20002], len, cnt;

int partition(int low, int high){
   int tmp = tmp_array[low];
   while(low
      while(low < high && tmp_array[high] > tmp)
         high --;
      if(low
         tmp_array[low++] = tmp_array[high];
      while(low < high && tmp_array[low] < tmp)
         low ++;
      if(low < high)
          tmp_array[high--] = tmp_array[low];
   }
   tmp_array[low] = tmp;
   return low;
}

void quick_sort(int low, int high){
    int index;
    if(low
       index = partition(low, high);
       quick_sort(low, index-1);
       quick_sort(index+1, high);
    }
}


int binaryInsert(int low, int high, int t){ //insert t in array, if not exist then insert, otherwise do not handle. all return the t pos.
   int mid = (low+high)/2;
   while(low <= high){
      if(t ==  array[mid]){
          return mid;
      }else if(t < array[mid]){
          high = mid - 1;
      }else{
          low = mid + 1;
      }
      mid = (low+high)/2;
   }
   return low;
}


void buildTree(int l, int r, int index){
   segTree[index].l = l;
   segTree[index].r = r;
   segTree[index].tab = 0;
   if(l!=r){
      buildTree(l,(l+r)/2,2*index);
      buildTree((l+r)/2+1,r,2*index+1);
   }
}

void changeTree(int l, int r, int index){
   if(segTree[index].l == l && r == segTree[index].r){ //恰巧覆蓋,則置爲頂層標號
      segTree[index].tab = num;
      //printf("改(%d -> %d)範圍值爲 %d.\n",l, r, num);
   }else{
       if(segTree[index].tab != 0){
          segTree[2*index].tab = segTree[index].tab;
          segTree[2*index+1].tab = segTree[index].tab;
          segTree[index].tab = 0;
       }
       if( l > (segTree[index].l+segTree[index].r)/2 ){ //右區域
          // printf("(%d->%d)在右區域\n",l, r);
           changeTree(l,r,2*index+1);
       }else if( r <= (segTree[index].l+segTree[index].r)/2 ){ //左區域
          // printf("(%d->%d)在左區域\n",l, r);
           changeTree(l,r,2*index);
       }else{ //橫跨兩個區域
          // printf("(%d->%d)跨兩個區域\n",l, r);
           changeTree(l,(segTree[index].l+segTree[index].r)/2,2*index);
           changeTree((segTree[index].l+segTree[index].r)/2+1,r,2*index+1);
       }
   }
}

void searchTree(int index){
   if(segTree[index].tab != 0){
      if(flag[segTree[index].tab] != 1){
         flag[segTree[index].tab] = 1;
         cnt ++;
      }
     
   }else{
      searchTree(2*index);
      searchTree(2*index+1);
   }
}

main(){
   int i, j, max, x[10001], y[10001], pos;
   int test;
  
   scanf("%d",&test);
   while(test > 0){
       test --;
      
       scanf("%d",&n);
      
       j=1;
       for(i=1;i<=n;i++){
           scanf("%d %d",&x[i], &y[i]);
           tmp_array[j++] = x[i];
           tmp_array[j++] = y[i];
          
       }
       memset(array,0,sizeof(array));
      
       //做快排後去重
       quick_sort(1,2*n); // for tmp_array
       array[1] = tmp_array[1];
       len = 1;
       for(i=2;i<=2*n;i++){// redupliction removing
           if(tmp_array[i]!=tmp_array[i-1])
               array[++len] = tmp_array[i];
       }
      
       //更新值——即所謂的“離散化”
       max = 0;
       for(i=1;i<=n;i++){
          x[i] = binaryInsert(1,len,x[i]);
          y[i] = binaryInsert(1,len,y[i]);
          if(y[i] > max)
             max = y[i];
       }
       for(i=1;i<=3*max;i++) //清空
           segTree[i].tab = 0;
    

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章