zoukankan      html  css  js  c++  java
  • 亚特兰蒂斯

    题目链接

    题意:给n个矩形到一个平面上,求他们的总面积。

    思路:将他们的x坐标从小到大排序,然后根据对于当前x坐标而言他们的y坐标区间进行相应的维护某些变化,这种解题思路就是扫描线。对于这题,我们要维护的是y区间的覆盖情况。

    然后用覆盖的总长度去乘以当前两个x之间的距离,再全部加起来就是答案。对于如何去计算每一个x后的y区间覆盖情况,我们可以令(x1,y1,y2,1)表示左区间,(x2,y1,y2,-1)为右区间。因为

    去累加的时候相当于在x2后面的就没覆盖到了。也就是说只有x1~x2的[y1,y2]区间被覆盖,还要维护个cnt表示被覆盖的次数。因为数据太大且为double记得离散化。

    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<queue>
    #include<cstdio>
    #include<cmath>
    #define ll long long
    #define lowbit(x) x&(-x)
    using namespace std;
    const int N=1000+10;
    struct node{
        double x,y1,y2;
        int val;
        node() {}
        node(double x, double y1, double y2,int val){
            this->x = x; this->val = val;
            this->y1 = y1; this->y2 = y2;
        }
        bool operator <(const node &t)const {
            return x<t.x;
        }
    };
    struct Tree
    {
        int l;
        int r;
        double len;
        int cnt;
     } t[N*2];
    vector<node> a;
    vector<double> y;
    int n;
    void pushup(int p)
    {
        int l=t[p].l;
        int r=t[p].r;
        if(t[p].cnt>0)
        {
            t[p].len=y[r+1]-y[l];
        }
        else
        {
            t[p].len=t[p<<1].len+t[p<<1|1].len;
        }
        
    }
    void build(int p,int l,int r)
    {
        t[p].l=l;
        t[p].r=r;
        t[p].cnt=t[p].len=0;
        if(l==r)
        return;
        int mid=(l+r)>>1;
        build(p<<1,l,mid);
        build(p<<1|1,mid+1,r);
    }
    void update(int p,int l,int r,int val)
    {
        if(t[p].l>=l&&t[p].r<=r)
        {
            t[p].cnt+=val;
            pushup(p);
            return;
        }
        int mid=(t[p].l+t[p].r)>>1;
        if(l<=mid)
        update(p<<1,l,r,val);
        if(r>mid)
        update(p<<1|1,l,r,val);
        pushup(p);
    }
    int main()
    {
        int k=1;
        while(~scanf("%d",&n)) 
        {
            if(n==0)
            break;
            y.clear();
            a.clear();
            for(int i=0;i<n;i++)
            {
                double x1,x2,y1,y2;
                scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
                y.push_back(y1);
                y.push_back(y2);
                a.push_back(node(x1,y2,y1,1));
                a.push_back(node(x2,y2,y1,-1));
            }
            y.push_back(-1);
            sort(a.begin(),a.end());
            sort(y.begin(),y.end());
            y.erase(unique(y.begin(),y.end()),y.end());
            int m=y.size(),num=a.size();
            build(1,0,m);
            double ans = 0.0;
            for(int i=0;i<num;i++)
            {
                int l=lower_bound(y.begin(),y.end(),a[i].y2)-y.begin();
                int r=lower_bound(y.begin(),y.end(),a[i].y1) - y.begin()-1;
                update(1,l,r,a[i].val);
                ans+=t[1].len*(a[i+1].x-a[i].x);
            }
            printf("Test case #%d
    ",k++);
            printf("Total explored area: %.2lf
    
    ",ans);
        }
        return 0;
     } 
  • 相关阅读:
    salmon 报错:ESC[00mException : [rapidjson internal assertion failure: IsObject()] salmon quant was invoked improperly.
    报错:RSEM can not recognize reference sequence name chr1!(基因组的bam不能直接用rsem进行表达值计算)
    R: 使用tapply根据相同ID合并指定列
    linux:去除特定列为空格的行
    知乎一答:程序员为什么要关注管理
    如何掌握一门编程语言的运用
    谈谈程序员这个职业及前景
    Oracle学习笔记(2)--Centos 7 下11gR2部署
    用flask写一个简单的接口
    iptables命令详解
  • 原文地址:https://www.cnblogs.com/2462478392Lee/p/11368866.html
Copyright © 2011-2022 走看看