Codeforces - 1194E - Count The Rectangles - 扫描线
https://codeforc.es/contest/1194/problem/E
给5000条正常的(同方向不会重叠,也不会退化成点的)线段,他们都是平行坐标轴方向的,求能组成多少个矩形。
先进行坐标偏移,按水平线和垂直线分好类。
用扫描线的思路,从底部的水平线开始往上扫,先标记所有与该条水平线相交的竖直线,加入队列,给竖直线按y排序。
先把结束的竖直线undo掉,然后从这条水平线A的下一条水平线B开始,询问B线覆盖的区间中还有多少标记的竖直线。
注意要么偏移5001,要么把区间查询这里加个特判。防止越界到-1。
慢一点点的代码。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 10001;
int bit[MAXN + 5];
inline int prefix_sum(int x) {
int res = 0;
for(; x; x -= x & -x)
res += bit[x];
return res;
}
inline void add(int x, int v) {
for(; x <= MAXN; x += x & -x)
bit[x] += v;
}
inline int range_sum(int l, int r) {
return prefix_sum(r) - prefix_sum(l - 1);
}
struct Vertical_Line {
int x, y1, y2;
bool operator<(const Vertical_Line& vl) {
return x != vl.x ? x < vl.x : y1 < vl.y1;
}
} vl[5005];
int vtop;
struct Vertical_Line_End {
int x, y;
bool operator<(const Vertical_Line_End& vle) {
return y < vle.y;
}
} vle[5005];
int vle_back, vle_front;
struct Horizontal_Line {
int x1, x2, y;
bool operator<(const Horizontal_Line& hl) {
return y != hl.y ? y < hl.y : x1 < hl.x1;
}
} hl[5005];
int htop;
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
//freopen("Yinku.out", "w", stdout);
#endif // Yinku
int n;
while(~scanf("%d", &n)) {
vtop = 0, htop = 0;
int x1, y1, x2, y2;
for(int i = 1; i <= n; i++) {
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
x1 += 5001, y1 += 5001, x2 += 5001, y2 += 5001;
if(x1 > x2)
swap(x1, x2);
if(y1 > y2)
swap(y1, y2);
if(x1 == x2) {
++vtop;
vl[vtop].x = x1;
vl[vtop].y1 = y1;
vl[vtop].y2 = y2;
} else {
++htop;
hl[htop].y = y1;
hl[htop].x1 = x1;
hl[htop].x2 = x2;
}
}
sort(vl + 1, vl + 1 + vtop);
sort(hl + 1, hl + 1 + htop);
ll ans = 0;
for(int hi = 1; hi <= htop; hi++) {
vle_front = 1;
vle_back = 0;
for(int vi = 1; vi <= vtop; vi++) {
if(vl[vi].x >= hl[hi].x1 && vl[vi].x <= hl[hi].x2 && vl[vi].y1 <= hl[hi].y && vl[vi].y2 >= hl[hi].y) {
add(vl[vi].x, 1);
++vle_back;
vle[vle_back].x = vl[vi].x;
vle[vle_back].y = vl[vi].y2;
}
}
sort(vle + 1, vle + 1 + vle_back);
int cury = hl[hi].y;
for(int hii = hi + 1; hii <= htop; hii++) {
while(vle_front <= vle_back && vle[vle_front].y < hl[hii].y) {
add(vle[vle_front].x, -1);
vle_front++;
}
int tmp = range_sum(hl[hii].x1, hl[hii].x2);
ans += (tmp * (tmp - 1) >> 1);
}
while(vle_front <= vle_back) {
add(vle[vle_front].x, -1);
vle_front++;
}
}
printf("%lld\n", ans);
}
}
其实一开始把竖直线也按y排序就省掉了后面的排序了的。快了一点点。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 10001;
int bit[MAXN + 5];
inline int prefix_sum(int x) {
int res = 0;
for(; x; x -= x & -x)
res += bit[x];
return res;
}
inline void add(int x, int v) {
for(; x <= MAXN; x += x & -x)
bit[x] += v;
}
inline int range_sum(int l, int r) {
return prefix_sum(r) - prefix_sum(l - 1);
}
struct Vertical_Line {
int x, y1, y2;
bool operator<(const Vertical_Line& vl) {
return y2 < vl.y2;
}
} vl[5005];
int vtop;
struct Vertical_Line_End {
int x, y;
} vle[5005];
int vle_back, vle_front;
struct Horizontal_Line {
int x1, x2, y;
bool operator<(const Horizontal_Line& hl) {
return y != hl.y ? y < hl.y : x1 < hl.x1;
}
} hl[5005];
int htop;
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
//freopen("Yinku.out", "w", stdout);
#endif // Yinku
int n;
while(~scanf("%d", &n)) {
vtop = 0, htop = 0;
int x1, y1, x2, y2;
for(int i = 1; i <= n; i++) {
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
x1 += 5001, y1 += 5001, x2 += 5001, y2 += 5001;
if(x1 > x2)
swap(x1, x2);
if(y1 > y2)
swap(y1, y2);
if(x1 == x2) {
++vtop;
vl[vtop].x = x1;
vl[vtop].y1 = y1;
vl[vtop].y2 = y2;
} else {
++htop;
hl[htop].y = y1;
hl[htop].x1 = x1;
hl[htop].x2 = x2;
}
}
sort(vl + 1, vl + 1 + vtop);
sort(hl + 1, hl + 1 + htop);
ll ans = 0;
for(int hi = 1; hi <= htop; hi++) {
vle_front = 1;
vle_back = 0;
for(int vi = 1; vi <= vtop; vi++) {
if(vl[vi].x >= hl[hi].x1 && vl[vi].x <= hl[hi].x2 && vl[vi].y1 <= hl[hi].y && vl[vi].y2 >= hl[hi].y) {
add(vl[vi].x, 1);
++vle_back;
vle[vle_back].x = vl[vi].x;
vle[vle_back].y = vl[vi].y2;
}
}
//sort(vle + 1, vle + 1 + vle_back);
int cury = hl[hi].y;
for(int hii = hi + 1; hii <= htop; hii++) {
while(vle_front <= vle_back && vle[vle_front].y < hl[hii].y) {
add(vle[vle_front].x, -1);
vle_front++;
}
int tmp = range_sum(hl[hii].x1, hl[hii].x2);
ans += (tmp * (tmp - 1) >> 1);
}
while(vle_front <= vle_back) {
add(vle[vle_front].x, -1);
vle_front++;
}
}
printf("%lld\n", ans);
}
}
Codeforces - 1194E - Count The Rectangles - 扫描线的更多相关文章
- Codeforces 1194E. Count The Rectangles
传送门 看到 $n<=5000$,直接暴力枚举左右两条竖线 然后考虑怎么计算高度在某个范围内,左端点小于等于某个值,右端点大于等于某个值的横线数量 直接用权值树状数组维护当前高度在某个区间内的横 ...
- Codeforces 1197E Count The Rectangles(树状数组+扫描线)
题意: 给你n条平行于坐标轴的线,问你能组成多少个矩形,坐标绝对值均小于5000 保证线之间不会重合或者退化 思路: 从下到上扫描每一条纵坐标为y的水平的线,然后扫描所有竖直的线并标记与它相交的线,保 ...
- Educational Codeforces Round 68 E. Count The Rectangles
Educational Codeforces Round 68 E. Count The Rectangles 传送门 题意: 给出不超过\(n,n\leq 5000\)条直线,问共形成多少个矩形. ...
- Codeforces 372 B. Counting Rectangles is Fun
$ >Codeforces \space 372 B. Counting Rectangles is Fun<$ 题目大意 : 给出一个 \(n \times m\) 的 \(01\) ...
- codeforces 713B B. Searching Rectangles(二分)
题目链接: B. Searching Rectangles time limit per test 1 second memory limit per test 256 megabytes input ...
- codeforces D. Count Good Substrings
http://codeforces.com/contest/451/problem/D 题意:给你一个字符串,然后找出奇数和偶数长度的子串的个数,这些字串符合,通过一些连续相同的字符合并后是回文串. ...
- CodeForces - 1189E Count Pairs(平方差)
Count Pairs You are given a prime number pp, nn integers a1,a2,…,ana1,a2,…,an, and an integer kk. Fi ...
- CodeForces 1216C(假的计算几何+扫描线)
传送门 •题意 给你三个矩形,依次编号为 1,2,3: 判断 矩形1 是否被 矩形2 和 矩形3 完全覆盖: 如果没有完全覆盖,输出 "YES",反之,输出 "NO&qu ...
- Codeforces 1188B - Count Pairs(思维题)
Codeforces 题面传送门 & 洛谷题面传送门 虽说是一个 D1B,但还是想了我足足 20min,所以还是写篇题解罢( 首先注意到这个式子里涉及两个参数,如果我们选择固定一个并动态维护另 ...
随机推荐
- Linux性能优化从入门到实战:15 文件系统篇:磁盘 I/O
磁盘 磁盘是可以持久化存储的设备,按照存储介质来分类: (1)机械磁盘(硬盘驱动器,Hard Disk Driver,HDD),主要由盘片和读写磁头组成,数据就存储在盘片的环状磁道中.在读写数 ...
- Oracle 数字转为字符串 to_char()
格式:TO_CHAR(number,'format_model') 9 -->Represents a number 0 --> Forces a zero to be displayed ...
- jsp基础模板
jsp页面基础模板 base.jsp <%@ page language="java" contentType="text/html; charset=UTF-8& ...
- VUE 生成二维码插件
原文:https://www.jianshu.com/p/496fd1cbee8d npm install qrcodejs2 --save 页面中引入 dom 结构 JS 方法编写 export d ...
- centos 6.5 安装 maven
从nexus官网下载Nexus Repository Manager OSS 2.x的安装包:nexus-2.14.1-01-bundle.tar.gz,3.x版本需要jdk8及以上 解压 tar x ...
- Queue2链队列
链队列 1 #include <iostream> using namespace std; template <class T> class Queue { private: ...
- [CSP-S模拟测试]:降雷皇(DP+树状数组)
题目描述 降雷皇哈蒙很喜欢雷电,他想找到神奇的电光.哈蒙有$n$条导线排成一排,每条导线有一个电阻值,神奇的电光只能从一根导线传到电阻比它大的上面,而且必须从左边向右传导,当然导线不必是连续的.哈蒙想 ...
- jinjia2 模板学习
参考链接https://blog.csdn.net/langkew/article/details/51734423
- ResultSet用法集锦 (转)
转:http://soft-development.iteye.com/blog/1420323 结果集(ResultSet)是数据中查询结果返回的一种对象,可以说结果集是一个存储查询结果的对象,但是 ...
- R python在无图形用户界面时保存图片
在用python的matplotlib,和R中自带的作图,如果想保存图片时,当你有图形用户界面时是没有问题的,但是当没有图形用户界面时,会报错: 在R中,解决办法: https://blog.csdn ...