算法与acm

poj1177 picture

2009年3月21日 阅读(285)

近来忙着挑战杯的项目,还有异构编程的,没有多少时间来做题,不过偶尔也会把题目记在心里,走路吃饭睡觉的时候那么想想。有时候也会有了一些新的看法和思考,感觉这样的思考方式倒是挺安静也挺深刻的,不会拘泥于做题中对数量的追求。

还是说说线段树吧,经典题目矩形并的周长,这个问题涉及的内容还比较多,包括排序,离散化,sweep line,还有线段树。

下面是一些问题,总体思路有了,细节上遇到的一些bug

1.线段树占用的空间大小?
为何分配了3*20000的大小,却在建立一个build(1,0,20000);的大小时内存访问溢出了?

void build(int node,int begin,int end){
    printf("%d %d %d\n",begin,end,node);
    seg_nodes[node].set_init();
    if(begin+1 == end){
        return;
    }
    build(2*node,begin,begin+(end-begin)/2);
    build(2*node+1,begin+(end-begin)/2,end);   
}
注意如果要用数组保存,则要关注线段树的深度,当20000的时候,其深度可以达到与32768同样的深度
纠正:将大小seg_nodes修改成4*20000

2.insert,dele失败
原因
    if(l <= begin && end <= r){
        seg_nodes[node].count++;
        update(node,begin,end);
        return ;
    }
语句忘记return;

3.我认为沿x轴方向和y轴方向的周长的计算方法是相同的。可是为何最终计算结果是错误的?
原因i++位置放错,而将x轴方向和y轴方向的周长等同处理的方法是正确的。
unsigned int sweep_line(segment array[],int size,int begin,int end){  
   unsigned long  area = 0;
   build(1,begin,end);
   int current,prev;
   current = prev = array[0].pos;
   for(int i = 0 ; i < size ; ){
      current = array[i].pos;
      area += (current – prev)*seg_nodes[1].c;     
      while(i < size && array[i].pos == current){    
            i++; 
            if(array[i].lor == 0){
                insert(1,begin,end,array[i].x,array[i].y);       
            }else{
                dele(1,begin,end,array[i].x,array[i].y);       
            }
      //i++ should be here. 
      }
      prev = current;

   }
   return area;
}

 

再附上完整的代码:

#include <iostream>
#include <cstdio>
#define MAX_N 20000*4
#define debug
#undef debug
struct node_t{
    int count;
    int c;
    bool lic;
    bool ric;
    void set_init(){
        count = 0;
        c = 0;
        lic = false;
        ric = false;
    }
} seg_nodes[MAX_N];
int num = 0;
void build(int node,int begin,int end){
    num++;
    //printf("%d %d %d\n",begin,end,node);
    seg_nodes[node].set_init();
    if(begin+1 < end){
        build(2*node,begin,begin+(end-begin)/2);
        build(2*node+1,begin+(end-begin)/2,end);   
    }
}
void update(int node,int begin,int end){
    //如果是叶子节点
    if(begin+1 == end){
        if(seg_nodes[node].count == 0){
            seg_nodes[node].lic = false;   
            seg_nodes[node].ric = false; 
            seg_nodes[node].c = 0; 
        }
        else{
            seg_nodes[node].lic = true;   
            seg_nodes[node].ric = true; 
            seg_nodes[node].c = 1; 
        }
    }
    //如果是内部节点
    else{
        if(seg_nodes[node].count == 0){
            seg_nodes[node].lic = seg_nodes[2*node].lic;   
            seg_nodes[node].ric = seg_nodes[2*node+1].ric;            
            seg_nodes[node].c =  seg_nodes[2*node].c + seg_nodes[2*node+1].c;
            if(seg_nodes[2*node].ric == true && seg_nodes[2*node+1].lic == true)
                     seg_nodes[node].c–;  
        }
        else{
            seg_nodes[node].lic = true;   
            seg_nodes[node].ric = true;  
            seg_nodes[node].c = 1; 
        }
    }
   

}
void insert(int node,int begin,int end,int l,int r){
    if(l <= begin && end <= r){
        seg_nodes[node].count++;
        update(node,begin,end);
        return ;
    }
    int mid = begin+(end-begin)/2;
    if(l < mid) insert(2*node,begin,mid,l,r);
    if(r > mid) insert(2*node+1,mid,end,l,r);
    update(node,begin,end);

}
void dele(int node,int begin,int end,int l,int r){
    if(l <= begin && end <= r){
        seg_nodes[node].count–;
        update(node,begin,end);
        return;
    }
    int mid = begin+(end-begin)/2;
    if(l < mid) dele(2*node,begin,mid,l,r);
    if(r > mid) dele(2*node+1,mid,end,l,r);
    update(node,begin,end);

}
struct segment{
    int pos;
    int lor;
    int x;
    int y;
    segment(){
        pos = lor = x = y = 0;
    }
    segment(int p,int l,int xx,int yy){
        pos = p;
        lor = l;
        x = xx;
        y = yy;
    }
}segs[2][5001*2];

void quick_sort(segment array[],int begin,int end){
    if(begin < end){
        int i,j;
        for(i = j = begin; i < end ; i++){
           if(array[i].pos < array[end].pos){
               segment temp = array[i];
               array[i] = array[j];
               array[j] = temp;
               j++;      
           }    
        }
        segment temp = array[end];
        array[end] = array[j];
        array[j] = temp;
        quick_sort(array,begin,j-1);
        quick_sort(array,j+1,end);
    }

}
unsigned int sweep_line(segment array[],int size,int begin,int end){  
   unsigned long  area = 0;
   build(1,begin,end);
   int current,prev;
   current = prev = array[0].pos;
   for(int i = 0 ; i < size ; ){
      current = array[i].pos;
      area += (current – prev)*seg_nodes[1].c;     
      while(i < size && array[i].pos == current){
            if(array[i].lor == 0){
                insert(1,begin,end,array[i].x,array[i].y);       
            }else{
                dele(1,begin,end,array[i].x,array[i].y);       
            }
            i++;
      }
      prev = current;

   }
   return area;
}
void printf_seg(segment array[],int size){
    printf("seg:\n");
    for(int i = 0 ; i < size ; i++){
        printf("%d(%d,%d) ",array[i].pos-10000,array[i].x-10000,array[i].y-10000);
    }
    printf("\n");
}
void test_insert_dele(int begin,int end){
  
   build(1,begin,end);
   printf("%d",num);
   insert(1,begin,end,1,3);
   insert(1,begin,end,4,5);
   insert(1,begin,end,3,4);
   dele(1,begin,end,4,5);
   printf("seg:%d",seg_nodes[1].c);

}
int main()
{
   //test_insert_dele(0,20000);
   int n;
   int index_x = 0;
   int index_y = 0;
   unsigned long length = 0;
   scanf("%d",&n);
   for(int i = 0 ; i < n ; i++){
      int llx,lly,urx,ury;
      scanf("%d%d%d%d",&llx,&lly,&urx,&ury);
      llx += 10000;
      lly += 10000;
      urx += 10000;
      ury += 10000;
      //x轴方向的下线段
      segs[0][index_x++] = segment(lly,0,llx,urx);
      //x轴方向的上线段
      segs[0][index_x++] = segment(ury,1,llx,urx);
      //y轴方向的左线段
      segs[1][index_y++] = segment(llx,0,lly,ury);
      //y轴方向的右线段
      segs[1][index_y++] = segment(urx,1,lly,ury);
   }  
   //线段排序  
   quick_sort(segs[0],0,index_x-1);
   //printf_seg(segs[0],index_x);
   quick_sort(segs[1],0,index_y-1);
   //printf_seg(segs[1],index_y);
   //建立线段树
   //
   length += sweep_line(segs[0],index_x,0,20000);
   //printf("%d\n",length*2);
   length += sweep_line(segs[1],index_y,0,20000);
   printf("%d\n",length*2);
    return 0;
}

You Might Also Like