zoukankan      html  css  js  c++  java
  • Atlantis(hdu1542)

    题意:求n个矩阵的面积并。

    /*
      线段树维护扫描线
      把每个矩形看成两条线段,从左到右添加线段,如果是矩形左边的线段,那就给线段所在的区间(y值)cover+1,反之则cover-1。
      并且如果这条线段添加之前它所在的区间的cover>0,则统计面积。
      另外如果求面积的交集,线段所在的区间的cover>1时统计面积。 
      
      PS:个人认为某位大神写的博客很好理解(这位大神还搞了一个线段树专辑?%%%):
         http://www.cnblogs.com/ka200812/archive/2011/11/13/2247064.html
         但是我觉得第一种算法每次都要找到叶子节点,貌似有点浪费时间,然而第二种又不会。。。 
    */
    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #define N 110
    using namespace std;
    double y[N*2];int n,cnt,Cas;
    struct node{
        double x,y_down,y_up;int flag;
        bool operator < (const node &s1)const{
            return x<s1.x;
        }
    };node e[N*2];
    struct Node{
        double x,y_down,y_up;int cover;
        int flag;//是否为叶子节点 
    };Node tree[1000*N];
    
    void build(int k,int l,int r){
        tree[k].cover=0;
        tree[k].x=-1;//代表这个区间最近一次的横坐标 
        tree[k].y_down=y[l];
        tree[k].y_up=y[r];
        tree[k].flag=0;
        if(l+1==r){
            tree[k].flag=1;
            return;
        }
        int mid=l+r>>1;
        build(k*2,l,mid);
        build(k*2+1,mid,r);
    }
    
    double insert(int k,double x,double l,double r,int flag){
        if(r<=tree[k].y_down||l>=tree[k].y_up) return 0;
        if(tree[k].flag){
            if(tree[k].cover>0){
                double ans=(x-tree[k].x)*(tree[k].y_up-tree[k].y_down);
                tree[k].cover+=flag;
                tree[k].x=x;
                return ans;
            }
            else {
                tree[k].cover+=flag;
                tree[k].x=x;
                return 0;
            }
        }
        double ans=0;
        ans+=insert(k*2,x,l,r,flag);
        ans+=insert(k*2+1,x,l,r,flag);
        return ans;
    }
    
    int main(){
        while(scanf("%d",&n)){
            if(!n) break;
            cnt=0;
            for(int i=1;i<=n;i++){
                double x1,y1,x2,y2;
                scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
                y[++cnt]=y1;
                e[cnt].x=x1;
                e[cnt].y_down=y1;
                e[cnt].y_up=y2;
                e[cnt].flag=1;
                y[++cnt]=y2;
                e[cnt].x=x2;
                e[cnt].y_down=y1;
                e[cnt].y_up=y2;
                e[cnt].flag=-1;
            }
            sort(y+1,y+cnt+1);//写成了sort(y,y+cnt+1),1WA 
            sort(e+1,e+cnt+1);
            build(1,1,cnt);
            double ans=0;
            for(int i=1;i<=cnt;i++){
                ans+=insert(1,e[i].x,e[i].y_down,e[i].y_up,e[i].flag);
            }
            printf("Test case #%d
    Total explored area: %.2f
    
    ",++Cas,ans);
        }
        return 0;
    }
  • 相关阅读:
    MongoDB:利用官方驱动改装为EF代码风格的MongoDB.Repository框架 二
    Ubuntu系统错误 没有公钥,无法验证下列签名: NO_PUBKEY 5F16B97C1AD28806
    Mysql数据库导出和导入
    Mysql清理binlog日志
    新手应该知道的流量概念
    xdebug对php程序性能分析
    mysql连接错误
    mysql导入导出命令
    mysql导出错误
    linux查看是软件是否安装
  • 原文地址:https://www.cnblogs.com/harden/p/6280026.html
Copyright © 2011-2022 走看看