hdu1255 覆盖的面积(线段树面积交)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255

面积交与面积并相似相比回了面积并,面积交一定会有思路,当然就是cover标记大于等于两次时。

但是操作起来发现与面积并有些不同。面积交要从面积并的状态转过来。当cover值为1的时候交

的长度可以为(p为当前节点len1为并的区间长度,len2为交的区间长度)

T[p].len2=T[p<<1].len1+T[(p<<1)|1].len1。这样也能满足cover为2.

当cover为2是那就与并的操作相同。

这题是一道比较简单的面积交模版题,可以拿来练练手。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
using namespace std;
const int M = 2e3 + 10;
double se[M << 1];
struct ss {
    double l , r , h;
    int flag;
}s[M << 1];
struct TnT {
    int l , r , add;
    double len1 , len2;
}T[M << 2];
bool cmp(ss a , ss b) {
    return a.h < b.h;
}
void build(int l , int r , int p) {
    int mid = (l + r) >> 1;
    T[p].l = l , T[p].r = r , T[p].len1 = T[p].len2 = T[p].add = 0;
    if(l == r)
        return ;
    build(l , mid , p << 1);
    build(mid + 1 , r , (p << 1) | 1);
}
void pushup(int p) {
    if(T[p].add >= 2) {
        T[p].len2 = se[T[p].r + 1] - se[T[p].l];
        T[p].len1 = T[p].len2;
    }
    else if(T[p].add == 1) {
        T[p].len1 = se[T[p].r + 1] - se[T[p].l];
        if(T[p].l == T[p].r) {
            T[p].len2 = 0;
        }
        else {
            T[p].len2 = T[p << 1].len1 + T[(p << 1) | 1].len1;
        }
    }
    else {
        if(T[p].l == T[p].r) {
            T[p].len1 = T[p].len2 = 0;
        }
        else {
            T[p].len1 = T[p << 1].len1 + T[(p << 1) | 1].len1;
            T[p].len2 = T[p << 1].len2 + T[(p << 1) | 1].len2;
        }
    }
}
void updata(int l , int r , int p , int ad) {
    int mid = (T[p].l + T[p].r) >> 1;
    if(T[p].l == l && T[p].r == r) {
        T[p].add += ad;
        pushup(p);
        return ;
    }
    if(mid >= r) {
        updata(l , r , p << 1 , ad);
    }
    else if(mid < l) {
        updata(l , r , (p << 1) | 1 , ad);
    }
    else {
        updata(l , mid , p << 1 , ad);
        updata(mid + 1 , r , (p << 1) | 1 , ad);
    }
    pushup(p);
}
int main() {
    int t , n;
    scanf("%d" , &t);
    while(t--) {
        scanf("%d" , &n);
        int cnt = 0;
        for(int i = 1 ; i <= n ; i++) {
            double x1 , x2 , y1 , y2;
            scanf("%lf%lf%lf%lf" , &x1 , &y1 , &x2 , &y2);
            s[i].flag = 1;
            s[i].l = x1;
            s[i].r = x2;
            s[i].h = y1;
            se[++cnt] = x1;
            se[++cnt] = x2;
            s[i + n].flag = -1;
            s[i + n].l = x1;
            s[i + n].r = x2;
            s[i + n].h = y2;
        }
        sort(se + 1 , se + 1 + cnt);
        sort(s + 1 , s + 1 + 2 * n , cmp);
        cnt = unique(se + 1 , se + 1 + cnt) - se - 1;
        build(1 , cnt , 1);
        int l , r;
        l = upper_bound(se + 1 , se + 1 + cnt , s[1].l) - se - 1;
        r = upper_bound(se + 1 , se + 1 + cnt , s[1].r) - se - 1;
        r--;
        double area = 0;
        updata(l , r , 1 , s[1].flag);
        for(int i = 2 ; i <= 2 * n ; i++) {
            area += T[1].len2 * (s[i].h - s[i - 1].h);
            l = upper_bound(se + 1 , se + 1 + cnt , s[i].l) - se - 1;
            r = upper_bound(se + 1 , se + 1 + cnt , s[i].r) - se - 1;
            r--;
            updata(l , r , 1 , s[i].flag);
        }
        printf("%.2lf\n" , area);
    }
    return 0;
}
时间: 2024-10-12 11:10:37

hdu1255 覆盖的面积(线段树面积交)的相关文章

HDU 1255 覆盖的面积(线段树面积并)

描述 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input 输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000. 注意:本题的输入数据较多,推荐使用scanf读入数据. Output 对于每组测试数据,请计算出

hdu 1255 覆盖的面积(线段树&amp;扫描线&amp;重复面积)

覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3375    Accepted Submission(s): 1645 Problem Description 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input 输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数

hdu 1255 覆盖的面积 线段树扫描线求重叠面积

稀里糊涂打完了没想到1A了,心情还是很舒畅的,c和c++的四舍五入还是四舍六入遇积进位遇偶舍,我感觉很混乱啊,这道题我输出的答案是7.62,也就是遇偶舍了,可是我就手动处理一下进位问题,发现0.005 系统自动进位0.01了,尼玛啊,我一下子就混乱了,不是遇偶舍么,0也是偶数啊,怎么就进位了呢.最后我就不手动处理进位问题了,直接0.2lf%,虽然我输出的结果是7.62,但是提交也过了 这道题和poj1151,hdu1542差不多,扫描线详细讲解http://blog.csdn.net/young

hdu1255--覆盖的面积(线段树+离散化+扫描线)

E - 覆盖的面积 Time Limit:5000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Description 给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input 输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含

hdu-1255-覆盖的面积-线段树

Splay树的插入操作,只需要处理好插入节点的孩子节点就可以了,最重要的是不要破坏了BST的基本规则. 因为高度并不是Splay树的首要因素,所以插入的时候也是使用splay操作,然后在根节点插入. 参考:http://www.geeksforgeeks.org/splay-tree-set-2-insert-delete/ 对比一下使用插入创建的树和手工创建数的区别,先序遍历的结果: #pragma once #include<stdio.h> #include <stdlib.h&g

hdu1255 覆盖的面积 线段树-扫描线

矩形面积并 线段树-扫描线裸题 1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<math.h> 5 using namespace std; 6 const int maxm=2e3+5; 7 const double eps=1e-5; 8 9 struct seg{ 10 double x,y1,y2; 11 int c; 12 bool operator

HDU 1255 覆盖的面积 (线段树+扫描线+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和. 因为n只有1000,所以我离散化一下,数据大小就缩小了,那么之后只需要线段树单点更新就好了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <map> 5 #include <algor

POJ 1389 Area of Simple Polygons 扫描线+线段树面积并

---恢复内容开始--- LINK 题意:同POJ1151 思路: /** @Date : 2017-07-19 13:24:45 * @FileName: POJ 1389 线段树+扫描线+面积并 同1151.cpp * @Platform: Windows * @Author : Lweleth ([email protected]) * @Link : https://github.com/ * @Version : $Id$ */ #include <stdio.h> #include

POJ 3171 区间最小花费覆盖 (DP+线段树

Cleaning Shifts Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4245   Accepted: 1429 Description Farmer John's cows, pampered since birth, have reached new heights of fastidiousness. They now require their barn to be immaculate. Farmer