并不对劲的CF1194E:Count The Rectangles
题意
有\(n\)(\(n\leq 5000\))个平行于x轴或平行于y轴的线段。求这些线段围成了多少个长方形。由多个长方形拼成的也算。
题解
考虑暴力的做法:先分别计算每条横着的线与哪些竖着的线有交点,再枚举两条横着的线,求与它们都有交点的线的个数,在这些线中选两条和这两条横着的线拼成长方形。
发现与同一条竖着的线有交点的横线一定是把所有横线按纵坐标排序后连续的一段。
感谢伟大的YSF!!!

代码
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define view(u,k) for(int k=fir[u];~k;k=nxt[k])
#define LL long long
#define maxn 5007
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)&&ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return x*f;
}
void write(LL x)
{
if(x==0){putchar('0'),putchar('\n');return;}
int f=0;char ch[20];
if(x<0)putchar('-'),x=-x;
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar('\n');
return;
}
struct node{int x,l,r;}a[maxn],b[maxn];
int n,tr[maxn+maxn],maxk=5001,sz=10002,cnta,cntb;
LL ans;
vector<int>ed[maxn];
node maken(int x,int l,int r){node tmp;tmp.x=x,tmp.l=l,tmp.r=r;return tmp;}
LL c(int x){return (LL)x*(x-1ll)/2ll;}
int lt(int x){return x&(-x);}
void add(int x,int k){for(;x<=sz;x+=lt(x))tr[x]+=k;return;}
int ask(int x){int k=0;for(;x;x-=lt(x))k+=tr[x];return k;}
int yes(node x,node y)
{
if(y.l<=x.x&&x.x<=y.r&&x.l<=y.x&&y.x<=x.r)return 1;
return 0;
}
bool cmpx(node x,node y){return x.x<y.x;}
bool cmpr(int x,int y){return b[x].r<b[y].r;}
int main()
{
n=read();
rep(i,1,n)
{
int x1=read(),y1=read(),x2=read(),y2=read();
if(x1>x2)swap(x1,x2);
if(y1>y2)swap(y1,y2);
if(y1==y2)a[++cnta]=maken(y1,x1,x2);
else b[++cntb]=maken(x1,y1,y2);
}
sort(a+1,a+cnta+1,cmpx);
rep(i,1,cnta)
{
rep(j,1,cntb)if(yes(a[i],b[j]))
{
add(b[j].x+maxk,1);
ed[i].push_back(j);
}
int li=ed[i].size(),now=-1;
sort(ed[i].begin(),ed[i].end(),cmpr);
rep(j,i+1,cnta)
{
while((now+1)<li&&b[ed[i][now+1]].r<a[j].x)add(b[ed[i][now+1]].x+maxk,-1),now++;
int num=ask(a[j].r+maxk)-ask(a[j].l+maxk-1);
ans+=c(num);
}
while((now+1)<li)add(b[ed[i][now+1]].x+maxk,-1),now++;
}
write(ans);
return 0;
}
并不对劲的CF1194E:Count The Rectangles的更多相关文章
- Educational Codeforces Round 68 E. Count The Rectangles
Educational Codeforces Round 68 E. Count The Rectangles 传送门 题意: 给出不超过\(n,n\leq 5000\)条直线,问共形成多少个矩形. ...
- 【EDU68 E】 Count The Rectangles 数据结构算几何
CF # 题意 总共有5000条线段,这些线段要么水平,要么垂直,问这些线段组成了多少矩形. # 思路 这是一个n*n*(log)的思路 自己一开始想着枚举两条垂直边,想着怎么把水平的边插入,再进行冗 ...
- Codeforces 1194E. Count The Rectangles
传送门 看到 $n<=5000$,直接暴力枚举左右两条竖线 然后考虑怎么计算高度在某个范围内,左端点小于等于某个值,右端点大于等于某个值的横线数量 直接用权值树状数组维护当前高度在某个区间内的横 ...
- Codeforces - 1194E - Count The Rectangles - 扫描线
https://codeforc.es/contest/1194/problem/E 给5000条正常的(同方向不会重叠,也不会退化成点的)线段,他们都是平行坐标轴方向的,求能组成多少个矩形. 先进行 ...
- Codeforces 1197E Count The Rectangles(树状数组+扫描线)
题意: 给你n条平行于坐标轴的线,问你能组成多少个矩形,坐标绝对值均小于5000 保证线之间不会重合或者退化 思路: 从下到上扫描每一条纵坐标为y的水平的线,然后扫描所有竖直的线并标记与它相交的线,保 ...
- 面向对象设计模式_享元模式(Flyweight Pattern)解读
场景:程序需要不断创建大量相似的细粒度对象,会造成严重的内存负载.我们可以选择享元模式解决该问题. 享元抽象:Flyweight 描述享元的抽象结构.它包含内蕴和外蕴部分(别被术语迷惑,这是一种比较深 ...
- Educational Codeforces Round 68
目录 Contest Info Solutions A.Remove a Progression B.Yet Another Crosses Problem C.From S To T D.1-2-K ...
- nodejs api 中文文档
文档首页 英文版文档 本作品采用知识共享署名-非商业性使用 3.0 未本地化版本许可协议进行许可. Node.js v0.10.18 手册 & 文档 索引 | 在单一页面中浏览 | JSON格 ...
- [ACM_暴力][ACM_几何] ZOJ 1426 Counting Rectangles (水平竖直线段组成的矩形个数,暴力)
Description We are given a figure consisting of only horizontal and vertical line segments. Our goal ...
随机推荐
- JavaEE三大框架的整合
JavaEE三大框架的整合 ...
- embeddable persistent key-value store for fast storage
A persistent key-value store for fast storage environmentsRocksDB is an embeddable persistent key-va ...
- 交叉编译多平台 FFmpeg 库并提取视频帧(转)
交叉编译多平台 FFmpeg 库并提取视频帧 转 https://www.cnblogs.com/leviatan/p/11142579.html 本文档适用于 x86 平台编译 armeabi.a ...
- Kali Linux更新5.2.9后 Vmware Workstation无法正常启动
说明本脚本仅作为学习使用,请勿用于任何商业用途.本文为原创,遵循CC 4.0 by-sa版权协议,转载请附上原文出处链接和本声明. 最近更新了Kali后发现一个奇葩的问题,我的虚拟机不能正常使用了.启 ...
- numpy中flatten学习笔记
ndarray.flatten() 用法 用于返回一个折叠成一维的数组.该函数只能适用于numpy对象,即array或者mat,普通的list列表是不行的. 例子 # coding=utf-8 fro ...
- [Java复习] Spring 常见面试问题
1. 什么是 Spring 框架?Spring 框架有哪些主要模块? 轻量级实现IoC和AOP的JavaEE框架. Core模块: bean(bean定义创建解析), context(环境, IoC容 ...
- Linux与linux之间传递文件、
1.从linux本机文件上传到另一台linux格式:scp 要传的文件 root@目标ip:路径scp –r 要传的目录 root@目标ip:路径 例子: scp /root/1.txt roo ...
- linux简单命令7--管道符和通配符
”&&“和管道符“|”不一样. ---------------------------------------------------------通配符---------------- ...
- JAVA 基础编程练习题43 【程序 43 求奇数个数】
43 [程序 43 求奇数个数] 题目:求 0—7 所能组成的奇数个数. package cskaoyan; public class cskaoyan43 { @org.junit.Test pub ...
- Freemarker使用总结
spring mvc 中 Freemarker 获取项目根目录,方便HTML页面配置各种路径 在SpringMVC框架中使用Freemarker试图时,要获取根路径的方式如下: <!-- Fre ...