【bzoj5173】[Jsoi2014]矩形并 扫描线+二维树状数组区间修改区间查询
题目描述
输入
输出
样例输入
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 <cstdio>
#include <cstring>
#include <algorithm>
#define N 200010
using 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;
}
【bzoj5173】[Jsoi2014]矩形并 扫描线+二维树状数组区间修改区间查询的更多相关文章
- 【bzoj3132】上帝造题的七分钟 二维树状数组区间修改区间查询
题目描述 “第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a,b),右下角为(c,d)的一个矩形区域内的全部数字加上一个值的操作. ...
- POJ2155 Matrix(二维树状数组||区间修改单点查询)
Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the i-th row an ...
- poj 2155 (二维树状数组 区间修改 求某点值)
Matrix Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 33682 Accepted: 12194 Descript ...
- 【poj2155】Matrix(二维树状数组区间更新+单点查询)
Description Given an N*N matrix A, whose elements are either 0 or 1. A[i, j] means the number in the ...
- TZOJ 2725 See you~(二维树状数组单点更新区间查询)
描述 Now I am leaving hust acm. In the past two and half years, I learned so many knowledge about Algo ...
- hdu 2642二维树状数组 单点更新区间查询 模板题
二维树状数组 单点更新区间查询 模板 从零开始借鉴http://www.2cto.com/kf/201307/227488.html #include<stdio.h> #include& ...
- 【bzoj4540】[Hnoi2016]序列 单调栈+离线+扫描线+树状数组区间修改区间查询
题目描述 给出一个序列,多次询问一个区间的所有子区间最小值之和. 输入 输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数.接下来一行,包含n个整数,以空格隔开,第i个整数为ai,即序列第i ...
- 【bzoj3779】重组病毒 LCT+树上倍增+DFS序+树状数组区间修改区间查询
题目描述 给出一棵n个节点的树,每一个节点开始有一个互不相同的颜色,初始根节点为1. 定义一次感染为:将指定的一个节点到根的链上的所有节点染成一种新的颜色,代价为这条链上不同颜色的数目. 现有m次操作 ...
- hdu 2642 二维树状数组 单点更新区间查询 模板水题
Stars Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/65536 K (Java/Others) Total Subm ...
随机推荐
- 安装虚拟机以及学习Linux基础入门
安装虚拟机 参考基于VirtualBox虚拟机安装Ubuntu图文教程完成了虚拟机的安装,主要遇到了以下2个问题 在新建虚拟电脑的时候,如果类型选择了Linux,则版本就只能选择Ubuntu(32 位 ...
- 20155336 2016-2017-2《JAVA程序设计》第二周学习总结
20155336 2016-2017-2 <JAVA 程序设计>第二周学习总结 教材学习内容 1: GIT版本检测 2: JAVA中基本类型 整数 字节 浮点数 字符 布尔(▲) 通过AP ...
- yaml中的锚点和引用
项目引入yaml语言来写配置文件,最近发现利用其锚点&和引用*的功能,可以极大减少配置文件中的重复内容,将相同配置内容收敛到锚点处,修改时,只需要修改锚点处的内容,即可在所有引用处生效. ya ...
- 同步备份工具之 rsync
1.常用同步方法 SCP. NFS. SFTP. http. samba. rsync. drbd(基于文件系统同步,效率高) 2.rsync 介绍 rsync,英文全称是 remote synchr ...
- 简单读取 properties文件
看了网上很多读取的方法,都太过复杂,直接使用下面的方法就可以简单读取 properties文件了 ide使用idea 测试读取成功 import java.util.ResourceBundle; p ...
- hive 数据导入
Hive的几种常见的数据导入方式这里介绍四种:(1).从本地文件系统中导入数据到Hive表:(2).从HDFS上导入数据到Hive表:(3).从别的表中查询出相应的数据并导入到Hive表中:(4).在 ...
- 动态权限<一>基本介绍
android 6.0以上为了保护用户的隐私,和以往被人诟病的权限机制,确立了新的权限机制.从 Android 6.0(API 级别 23)开始,用户开始在应用运行时向其授予权限,而不是在应用安装时授 ...
- ubuntu dpkg出现语法错误:安装软件提示无效组件
当安装软件是提示组件错误而导致不能安装,特别是以前卸载软件之后,再安装新版本的软件,其实就是之前卸载的时候没有按照正确的方法卸载引起的 解决方法如下: 使用sudo授权 1. 列出sudo dpkg ...
- OKHttp使用demo(证书过滤,证书导入,代理访问,文件上传)
此demo需要引入okhttp-3.4.1.jar 和 okio-1.9.0.jar(这两个包需要jdk1.7以上的环境) 对应pom文件是: <dependency> <group ...
- ovs源码阅读--流表查询原理
背景 在ovs交换机中,报文的处理流程可以划分为一下三个步骤:协议解析,表项查找和动作执行,其中最耗时的步骤在于表项查找,往往一个流表中有数目巨大的表项,如何根据数据报文的信息快速的查找到对应的流表项 ...