题目描述

平面上有$n$个点,第$i$个点的坐标为$X_i,Y_i$。对于其中的一个非空点集$S$,定义$f(S)$为一个最小矩形,满足:
$\bullet$覆盖$S$中所有的点(在边界上也算覆盖);
$\bullet$边与坐标轴平行。
求所有不同的$f(S)$的面积和对$10^9+7$取模的结果。两个矩形被认为是不同的,当且仅当它们顶点坐标不同。


输入格式

从文件$rectangle.in$中读入数据。
第一行一个整数$n$。
接下来$n$行,每行两个整数$X_i,Y_i$。


输出格式

输出到文件$rectangle.out$中。
一行一个整数表示答案。


样例

样例输入:

4
1 2
3 1
4 4
5 1

样例输出:

45


数据范围与提示

样例解释:

有$8$个面积大于$0$的不同矩形,以下是它们左下角和右上角的坐标:
$(1,1),(3,2);(1,1),(4,4);(1,1),(5,2);(1,1),(5,4)$
$(1,2),(4,4);(3,1),(4,4);(3,1),(5,4);(4,1),(5,4)$

数据范围:

对于所有数据,满足$2\leqslant n\leqslant 10^4,1\leqslant X_i,Y_i\leqslant 2500$,没有重复的点。
$\bullet Subtask1(13\%)$,$n\leqslant 18$。
$\bullet Subtask2(9\%)$,$n\leqslant 50$。
$\bullet Subtask3(25\%)$,$n\leqslant 300$。
$\bullet Subtask4(21\%)$,$n\leqslant 2500,X_i\neq X_j,Y_i\neq Y_j$。
$\bullet Subtask5(19\%)$,$n\leqslant 2500$。
$\bullet Subtask6(13\%)$,没有特殊的约束。


题解

先来考虑$21\%$的$X_i\neq X_j,Y_i\neq Y_j$的情况。

我们可以$n^2$枚举左右边界,那么设边界上的点为$(L,y_1)$和$(R,y_2)$。

那么只有位于$(L,R)$且纵坐标$>\max(y_1,y_2)$和$<\min(y_1,y_2)$的点才能做贡献,我们可以考虑树状数组,存储$\sum y$即可(长度是变化的,但是高度不变)。

现在来考虑一般情况,每个$L$和$R$上可能有很多的点,我们依次枚举计数即可。

但是可能会出现如下图中的情况:

显然,我们在统计答案点$1,3$和点$2,3$的贡献的时候会将紫色矩阵算重,不用担心,我们只需要将纵坐标最靠下的统计就好了。

代码实现稍繁琐。

时间复杂度:$\Theta(nm\log m)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
using namespace std;
const int mod=1000000007;
int n;
int Map[2501][2501];
int tr[2][2501][2501];
bool vis[2501][2501];
long long ans;
int lowbit(int x){return x&-x;}
void add(int id,int k,int x,int w)
{
for(int i=x;i<=2500;i+=lowbit(i))
tr[id][k][i]+=w;
}
int ask(int id,int k,int x)
{
int res=0;
for(int i=x;i;i-=lowbit(i))res+=tr[id][k][i];
return res;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
Map[x][++Map[x][0]]=y;
}
for(int i=1;i<=2500;i++)
{
sort(Map[i]+1,Map[i]+Map[i][0]+1);
Map[i][Map[i][0]+1]=2501;
}
for(int i=1;i<=2500;i++)
{
if(!Map[i][0])continue;
for(int j=1;j<=Map[i][0];j++)
if(!vis[i][Map[i][j]])
{
vis[i][Map[i][j]]=1;
add(1,i,Map[i][j],1);
add(0,i,Map[i][j],Map[i][j]);
}
for(int j=i-1;j;j--)
{
if(!Map[j][0])continue;
int l1=1,l2=1;
for(int k=1;k<=Map[j][0];k++)
if(!vis[i][Map[j][k]])
{
vis[i][Map[j][k]]=1;
add(1,i,Map[j][k],1);
add(0,i,Map[j][k],Map[j][k]);
}
int wzc=max(Map[i][1],Map[j][1]);
while(Map[i][l1+1]<=wzc)l1++;
while(Map[j][l2+1]<=wzc)l2++;
while(l1<=Map[i][0]&&l2<=Map[j][0])
{
int flag=min(Map[i][l1+1],Map[j][l2+1]);
ans=(ans+1LL*(i-j)*((ask(0,i,flag-1)-ask(0,i,wzc-1))*ask(1,i,min(Map[i][l1],Map[j][l2]))-((ask(1,i,flag-1)-ask(1,i,wzc-1))*ask(0,i,min(Map[i][l1],Map[j][l2])))))%mod;
wzc=flag;
if(Map[i][l1+1]<=wzc)l1++;
if(Map[j][l2+1]<=wzc)l2++;
}
}
}
printf("%lld\n",ans);
return 0;
}

rp++

[CSP-S模拟测试]:Rectangle(模拟+树状数组)的更多相关文章

  1. [CSP-S模拟测试]:柱状图(树状数组+二分+三分)

    题目描述 $WTH$获得了一个柱状图,这个柱状图一共有$N$个柱子,最开始第$i$根柱子的高度为$x_i$,他现在要将这个柱状图排成一个屋顶的形状,屋顶的定义如下:$1.$屋顶存在一个最高的柱子,假设 ...

  2. [CSP-S模拟测试]:影魔(树状数组+线段树合并)

    题目背景 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...

  3. [CSP-S模拟测试]:统计(树状数组+乱搞)

    题目传送门(内部题120) 输入格式 第一行,两个正整数$n,m$. 第二行,$n$个正整数$a_1,a_2,...,a_n$,保证$1\leqslant a_i\leqslant n$,可能存在相同 ...

  4. poj 2299 树状数组求逆序对数+离散化

    Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 54883   Accepted: 20184 ...

  5. The Stream of Corning 2( 权值线段树/(树状数组+二分) )

    题意: 有两种操作:1.在[l,r]上插入一条值为val的线段 2.问p位置上值第k小的线段的值(是否存在) 特别的,询问的时候l和p合起来是一个递增序列 1<=l,r<=1e9:1< ...

  6. 【CSP模拟赛】奇怪的队列(树状数组 &二分&贪心)

    题目描述 nodgd的粉丝太多了,每天都会有很多人排队要签名.  今天有n个人排队,每个人的身高都是一个整数,且互不相同.很不巧,nodgd今天去忙别的事情去了,就只好让这些粉丝们明天再来.同时nod ...

  7. [CSP-S模拟测试]:序列(二分答案+树状数组)

    题目传送门(内部题98) 输入格式 第一行一个整数$n$,第二行$n$个整数$a_1\sim a_n$,第三行$n$个整数$b_1\sim b_n$. 输出格式 一行一个整数表示$\max(r-l+1 ...

  8. [CSP-S模拟测试]:小P的单调数列(树状数组+DP)

    题目描述 小$P$最近喜欢上了单调数列,他觉得单调的数列具有非常多优美的性质.经过小$P$复杂的数学推导,他计算出了一个单调增数列的艺术价值等于该数列中所有书的总和.并且以这个为基础,小$P$还可以求 ...

  9. [CSP-S模拟测试]:降雷皇(DP+树状数组)

    题目描述 降雷皇哈蒙很喜欢雷电,他想找到神奇的电光.哈蒙有$n$条导线排成一排,每条导线有一个电阻值,神奇的电光只能从一根导线传到电阻比它大的上面,而且必须从左边向右传导,当然导线不必是连续的.哈蒙想 ...

随机推荐

  1. Azylee.Utils 工具组

    https://github.com/yuzhengyang/Fork Fork 是平时做 C# 软件的时候,整合各种轮子的一个工具项目,包括并不仅限于:各种常用数据处理方法,文件读写 加密 搜索,系 ...

  2. window.open弹窗阻止问题解决之道

    https://segmentfault.com/a/1190000015381923https://segmentfault.com/a/1190000014988094https://www.cn ...

  3. vue封装element中table组件

    后台系统,table被用的次数比较多,所以决定提出来作为组件 1.新建一个Table.vue文件 <!--region 封装的分页 table--> <template>  & ...

  4. Ngix 配置与部署(wsgi,uwsgi,uWSGI)

    1. WSGI 是一种协议接口,他是描述web服务器如何与web应用程序(Django ,Flask ) 通讯的规范. 2. uwsgi 与WSGI协议一样,是uWSGI服务器的独占协议,用于定义传输 ...

  5. 结合element-ui封装的一个分页函数

    第一次写博客,专门写给菜鸟看的,如果你是老鸟,你可以直接无视. 首先我们从豆瓣api获取到电影的数据列表 然后我们把他们切成一块一块的小数组 最后的数组将会是这样  原理就是以上的内容,接下来直接附上 ...

  6. python字典-基础

    一.解释 像列表一样,“字典”是许多值的集合.但不像列表的下标,字典的索引可以 使用许多不同数据类型,不只是整数.字典的索引被称为“键”,键及其关联的值 称为“键-值”对. 二.列表创建方式 1. I ...

  7. Spring MVC-学习笔记(3)参数绑定注解、HttpMessageConverter<T>信息转换、jackson、fastjson、XML

    1.参数绑定注解 1>@RequestParam: 用于将指定的请求参数赋值给方法中的指定参数.支持的属性: 2>@PathVariable:可以方便的获得URL中的动态参数,只支持一个属 ...

  8. [常用类]Math、Random、System、BigInteger、BigDecimal

    Math类中的成员全是静态成员,构造方法是 私有的,以避免被创建对象 常用方法: int abs() double ceil() //向上取整 double floor() //向下取整 int ma ...

  9. Redis的持久化存储

    Redis的持久化 Redis 是一种内存型数据库,一旦服务器进程退出,数据库的数据就会丢失,为了解决这个问题, Redis 提供了两种持久化的方案,将内存中的数据保存到磁盘中,避免数据的丢失. RD ...

  10. python学习第五十天shutil模块的用法

    什么shutil模块,就是对高级的文件,文件夹,压缩包进行处理的模块,下面简单讲述其用法. 文件和文件夹的操作 拷贝文件内容 import shutil shutil.copyfileobj(open ...