博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【bzoj5173】[Jsoi2014]矩形并 扫描线+二维树状数组区间修改区间查询
阅读量:5095 次
发布时间:2019-06-13

本文共 2744 字,大约阅读时间需要 9 分钟。

题目描述

JYY有N个平面坐标系中的矩形。每一个矩形的底边都平行于X轴,侧边平行于Y轴。第i个矩形的左下角坐标为(Xi,Yi),底边长为Ai,侧边长为Bi。现在JYY打算从这N个矩形中,随机选出两个不同的矩形,并计算它们的并的大小。JYY想知道,交的大小的期望是多少。换句话说即求在所有可能的选择中,两个矩形交的面积的平均大小是多大。

输入

输入一行包含一个正整数N。
接下来N行,每行4个整数,分别为Xi,Yi,Ai,Bi
2 < =  N < =  2*10^5, 0 < =  Xi, Yi, Ai, Bi < =  10^6。

输出

输出一行包含一个实数,表示矩形并的大小的期望。

样例输入

4

0 0 3 5
2 1 3 5
3 3 3 5
0 5 3 5

样例输出

1.833333333


题解

扫描线+二维树状数组区间修改区间查询

显然题目相当于:先给每个矩形内的权值+1,再查询每个矩形内的权值和即为任意选出两个矩形(可以相同,有顺序)的交面积的和,再减去每个矩形的面积(自己和自己)即得选出两个不同矩形的交面积之和。

那么我们把修改和询问差分成4个端点,就相当于统计每个询问拆出点的左下修改拆出点的贡献。使用扫描线维护。

注意到我们要做的是矩形加、矩形求和,可以使用  的方法,扫描线、一维树状数组方法类似。

最后除以 $n(n-1)$ 即可得到答案。

然而本题最恶心一点:本题爆long long!因此只能使用long double大法。由于最终答案只有 $10^{12}$ 级别,因此long double的精度是够的,不需要担心精度问题。

时间复杂度 $O(n\log n)$ 

#include 
#include
#include
#define N 200010using namespace std;typedef long double ld;int k;struct bit{ ld f[N << 2]; inline void add(int x , ld a) { int i; for(i = x ; i <= k ; i += i & -i) f[i] += a; } inline ld ask(int x) { int i; ld ans = 0; for(i = x ; i ; i -= i & -i) ans += f[i]; return ans; }}A , B , C , D;struct data{ ld x; int y , z , val; bool operator<(const data &a)const {return x < a.x;}}a[N << 1] , b[N << 1];ld v[N << 2];inline void modify(ld x , int y , int a){ A.add(y , a) , B.add(y , x * a) , C.add(y , v[y] * a) , D.add(y , x * v[y] * a);}inline ld query(ld x , int y){ return (x + 1) * (v[y] + 1) * A.ask(y) - (v[y] + 1) * B.ask(y) - (x + 1) * C.ask(y) + D.ask(y);}int main(){ int n , i , p = 1; ld xi , yi , ai , bi , ans = 0 , sum; scanf("%d" , &n) , sum = (ld)n * (n - 1); for(i = 1 ; i <= n ; i ++ ) { scanf("%Lf%Lf%Lf%Lf" , &xi , &yi , &ai , &bi) , ans -= ai * bi; a[i].x = xi , a[i].y = yi , a[i].z = yi + bi , a[i].val = 1; b[i].x = xi - 1 , b[i].y = yi - 1 , b[i].z = yi + bi - 1 , b[i].val = -1; a[i + n].x = xi + ai , a[i + n].y = yi , a[i + n].z = yi + bi , a[i + n].val = -1; b[i + n].x = xi + ai - 1 , b[i + n].y = yi - 1 , b[i + n].z = yi + bi - 1 , b[i + n].val = 1; v[++k] = yi , v[++k] = yi + bi , v[++k] = yi - 1 , v[++k] = yi + bi - 1; } sort(v + 1 , v + k + 1) , k = unique(v + 1 , v + k + 1) - v; for(i = 1 ; i <= 2 * n ; i ++ ) { a[i].y = lower_bound(v + 1 , v + k + 1 , a[i].y) - v; a[i].z = lower_bound(v + 1 , v + k + 1 , a[i].z) - v; b[i].y = lower_bound(v + 1 , v + k + 1 , b[i].y) - v; b[i].z = lower_bound(v + 1 , v + k + 1 , b[i].z) - v; } sort(a + 1 , a + 2 * n + 1) , sort(b + 1 , b + 2 * n + 1); for(i = 1 ; i <= 2 * n ; i ++ ) { while(p <= 2 * n && a[p].x <= b[i].x) modify(a[p].x , a[p].y , a[p].val) , modify(a[p].x , a[p].z , -a[p].val) , p ++ ; ans += b[i].val * (query(b[i].x , b[i].z) - query(b[i].x , b[i].y)); } printf("%.9Lf\n" , ans / sum); return 0;}

 

 

转载于:https://www.cnblogs.com/GXZlegend/p/8485611.html

你可能感兴趣的文章
使用SSIS同步数据库数据
查看>>
iOS学习总结之ARC和非ARC的单例模式实现
查看>>
MapReduce业务 - 图片关联计算
查看>>
误用的volatile
查看>>
CI框架程序--本地调试之后部署新浪SAE
查看>>
Oracle 从缓存里面查找真实的执行计划
查看>>
函数参数详解
查看>>
01: docker 基本使用
查看>>
Django--自定义 Command 命令
查看>>
Windows 10 SDK 10.0.10158
查看>>
Delphi 调用C#编写的WebService 参数为Null解决方法
查看>>
手动完美去除Windows 7 快捷方式小箭头
查看>>
The last packet successfully received from the server was 39,900 milliseconds ago问题解决
查看>>
编译前端工具
查看>>
xming2
查看>>
特征工程入门
查看>>
『嗨威说』数据结构 - 第三章学习内容小结
查看>>
Mac复制粘贴文本时默认使用无格式模式
查看>>
[使用经验]cocostudio UI编辑器的裁剪
查看>>
selenium,控制滚动条
查看>>