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,所以还是写篇题解罢( 首先注意到这个式子里涉及两个参数,如果我们选择固定一个并动态维护另 ...
随机推荐
- Nginx优化_自定义报错页面
自定义返回给客户端的404错误页面 1. 优化前,客户端使用浏览器访问不存在的页面,会提示404文件未找到 client]# firefox http://192.168.4.5/xxxxx ...
- linux7 grub配置文件 linux6 grub配置文件
在 grub 的 kernel 配置后面,添加 acpi_pad.disable=1 重启机器之后,开机就不会自动加载 acpi_pad 模块 一:linux6 [root@node2 ~]# cat ...
- [USACO]奶牛会展(背包)
[USACO]奶牛会展 题目背景 奶牛想证明它们是聪明而风趣的.为此,贝西筹备了一个奶牛博览会,她已经对N 头奶牛进行 了面试,确定了每头奶牛的智商和情商. 题目描述 贝西有权选择让哪些奶牛参加展览. ...
- Angular Viewchild undefined
Angular的viewchild在使用的时候报错 undefined 1 检查是否在元素上打上标识 #xxx 2 查看引用元素时的时机 是否在AfterViewInit之后 3 检查元素是否在*ng ...
- python3-disc和set
dict Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度. 举个例子,假设要根据同学的名字 ...
- Java 逻辑运算符相关解析
问:定简单说说 Java 中 & 与 && 有什么区别?| 与 || 呢? 答:& 是位运算符,&& 是布尔逻辑运算符,| 与 || 类似同理.在进行逻 ...
- Julia 语言
同时安装多个库 Pkg.add.(["IJulia", "Combinatorics", "Plots", "TaylorSeri ...
- Dubbo 在跨语言和协议穿透性方向的探索:支持 HTTP/2 gRPC
Dubbo 在跨语言和协议穿透性方向上的探索:支持 HTTP/2 gRPC 和 Protobuf 本文整理自刘军在 Dubbo 成都 meetup 上分享的<Dubbo 在多语言和协议穿透性方向 ...
- 全国地区sql表
/** * 中国省市区--地区SQL表 */ CREATE TABLE `rc_district` ( `id` smallint(5) unsigned NOT NULL AUTO_INCREMEN ...
- Linux shell - scp命令用法
例子: 远程复制一个文件从服务器A (172.0.0.0) /home/test/file1.txt 到 服务器B (172.0.0.1) /home/test 服务器A和服务器B的用户是 test ...