zoukankan      html  css  js  c++  java
  • HDU1255

    Description

    给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.

    思路

    和单纯的求面积非常相似,用len来储存被覆盖到两次以上的区间长度。

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    #define endl '
    '
    typedef long long ll;
    
    const int N = 3000;
    
    struct snode {
        double x, y1, y2;
        int flag;
        
    };
    
    bool cmp(const snode &a, const snode &b) {
        return a.x < b.x;
    }
    
    struct tnode {
        double sum, l, r, len;
    };
    
    tnode st[N << 2];
    snode seg[N];
    double num[N];
    int lazy[N << 2];
    
    void pushup(int rt) {
        if(lazy[rt] > 0) {
            st[rt].sum = st[rt].r - st[rt].l;
            if(lazy[rt] > 1) st[rt].len = st[rt].sum;
            else st[rt].len = st[rt << 1].sum + st[rt << 1 | 1].sum;
        } else {
            st[rt].sum = st[rt << 1].sum + st[rt << 1 | 1].sum;
            st[rt].len = st[rt << 1].len + st[rt << 1 | 1].len;
        }
    
    }
    
    void update(double L, double R, int rt, int flag) {
        if(L == st[rt].l && R == st[rt].r) {
            lazy[rt] += flag;
            pushup(rt);
            return ;
        }
        if(st[rt << 1].r > L) //>而不是>=?不能等于,否则长度为0,会进入死循环。
            update(L, min(R, st[rt << 1].r), rt << 1, flag);
        if(st[rt << 1 | 1].l < R) 
            update(max(L, st[rt << 1 | 1].l), R, rt << 1 | 1, flag);
        pushup(rt);
    }
    
    void build(int lef, int rig, int rt) {
        if(rig - lef > 1) { //由于mid公用,所以>1就可以
            int mid = (lef + rig) / 2;
            st[rt].l = num[lef];
            st[rt].r = num[rig];
            build(lef, mid, rt << 1);
            build(mid, rig, rt << 1 | 1); //mid而不是mid+1?因为是线段,头尾需要相连,否则会少值
            pushup(rt);
        } else {
            st[rt].l = num[lef];
            st[rt].r = num[rig];
            st[rt].sum = 0;
            st[rt].len = 0;
        }
    }
    
    
    int main() {
        
        //ios::sync_with_stdio(false);
        int n;
        int t;
        scanf("%d", &t);
        while(t--) {
            scanf("%d", &n);
            if(!n) break;
            for(int i = 0; i < n; i++) {
                double x1, x2, y1, y2;
                scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);
                seg[i].x = x1; seg[i].y1 = y1; seg[i].y2 = y2; 
                seg[i].flag = 1;
                seg[i + n].x = x2; seg[i + n].y1 = y1; seg[i + n].y2 = y2; 
                seg[i + n].flag = -1;
    
                num[i + 1] = y1;
                num[i + 1 + n] = y2;
            }
            sort(num + 1, num + 1 + (2 * n));
            sort(seg, seg + 2 * n, cmp);
            memset(lazy, 0, sizeof lazy);
            build(1, 2 * n, 1);
            double ans = 0;
            update(seg[0].y1, seg[0].y2, 1, seg[0].flag);
            for(int i = 1; i < 2 * n; i++) {
                ans += (seg[i].x - seg[i - 1].x) * st[1].len;
                //cout << st[1].len << endl;
                update(seg[i].y1, seg[i].y2, 1, seg[i].flag);
                //cout << seg[i].x << " " << seg[i].y1 << " " << seg[i].y2 << endl;
            }
            printf("%.2lf
    ", ans);
            //printf("Total explored area: %.2lf
    
    ", ans);
        }
    }
    
  • 相关阅读:
    vue中局部过滤器的使用
    elementui中switch开关的回调的使用
    css居中的一些方法
    elementui默认样式修改的几种方法
    git查看远程分支,并且切换到远程的分支
    elementui form resetFields方法 无法重置表单
    vue组件使用vuex中的方法报错,报unknown mutation type的错误
    offSet和client和scroll
    842. Split Array into Fibonacci Sequence能否把数列返回成斐波那契数列
    662. Maximum Width of Binary Tree二叉树的最大宽度
  • 原文地址:https://www.cnblogs.com/limil/p/12741560.html
Copyright © 2011-2022 走看看