HDU 1542

HDU 1542
http://acm.hdu.edu.cn/showproblem.php?pid=1542
// 线段树+离散化计算覆盖矩形的面积并
// 经典题目
#include  < iostream >
#include 
< algorithm >
#include 
< map >
#include 
< iomanip >
#include 
< stdio.h >
using   namespace  std;

typedef pair
< double , int >  mypair; // 用于将double型的长度和int型的区间关联
double  x[ 201 ],y[ 201 ],mx[ 201 ],my[ 201 ]; // x,y存储原始数据,mx,my存储排序后的数据
map < double , int >  m;
double  lenth; // 用于计算每回合覆盖的总长度

class  tree  // segment tree
{
public:
    
int begin,end,mid;
    
bool isoccupied;
    tree 
*left,*right; 
    tree()
{}
    tree(
int a,int b)//create tree
    {
        begin
=a;
        end
=b;
        mid
=(a+b)/2;
        
if(begin+1!=end)//若不是叶子节点,则递归建立线段树
        {
            left
=new tree(a,mid);
            right
=new tree(mid,b);
        }

    }


    
void clear()//clear tree
    {
        isoccupied
=false;
        
if(begin+1!=end)
        
{
            left
->clear();
            right
->clear();
        }

     }


    
void modify(int a,int b)//modify tree
    {
        
if(a>b)
            swap(a,b);
        
if(a==begin && b==end)//遇到正好标记的段,返回,不需要向下标记
        {
            isoccupied
=true;
            
return;
        }

        
if(begin+1==end)
        
return ;
        
if(b<=mid)
            left
->modify(a,b);
        
else if(a>=mid)
            right
->modify(a,b);
        
else
        
{
            left
->modify(a,mid);
            right
->modify(mid,b);
        }

    }


    
void sum()//compute sum
    {
        
if(isoccupied==true//只计算正好标记的段,防止重复计算
        {
            lenth
+=my[end]-my[begin];
            
return ;
        }

        
if(begin+1==end)
        
{
            
return;
        }

        
else
        
{
            left
->sum();
            right
->sum();
        }

    }

}
;

int  main()
{
    
int i=1,n,j,k;
    
double result;
    
while(scanf("%d",&n),n)
    
{
        result
=0;//每次都要初始化
        m.clear();//清空树
        for(j=0;j<n;j++)
        
{
            scanf(
"%lf %lf %lf %lf",&x[2*j],&y[2*j],&x[2*j+1],&y[2*j+1]);
        }

        
for(j=0;j<2*n;j++)
        
{
            mx[j]
=x[j];
            my[j]
=y[j];
        }

        sort(mx,mx
+2*n);
        sort(my,my
+2*n);
        
for(j=0;j<2*n;j++)//将y坐标与区间关联,查找方便
            m.insert(mypair(my[j],j));
        tree 
*root=new tree(0,2*n-1);//建立线段树,注意从0开始,因为my数组是从0开始的,要保持照应
        for(j=0;j<2*n-1;j++//注意是2*n-1,不是2*n
        {
            
double temp=mx[j+1]-mx[j];//横向分割段长
            lenth=0;                  //纵向段长清零
            root->clear();            //每次都要重新计算纵向段长
            for(k=0;k<n;k++)
            
{
                
if(x[2*k]<=mx[j] && x[2*k+1]>=mx[j+1])//当某矩形纵向包含当前分割段时,说明它包含要计算的块
                    root->modify(m[y[2*k]],m[y[2*k+1]]);//调整y[2*k],y[2*k+1]对应的段
            }

            root
->sum();
            result
+=temp*lenth;
        }

        printf(
"Test case #%d\nTotal explored area: %.2f\n\n",i++,result);
    }

}



你可能感兴趣的:(HDU 1542)