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 - 扫描线的更多相关文章

  1. Codeforces 1194E. Count The Rectangles

    传送门 看到 $n<=5000$,直接暴力枚举左右两条竖线 然后考虑怎么计算高度在某个范围内,左端点小于等于某个值,右端点大于等于某个值的横线数量 直接用权值树状数组维护当前高度在某个区间内的横 ...

  2. Codeforces 1197E Count The Rectangles(树状数组+扫描线)

    题意: 给你n条平行于坐标轴的线,问你能组成多少个矩形,坐标绝对值均小于5000 保证线之间不会重合或者退化 思路: 从下到上扫描每一条纵坐标为y的水平的线,然后扫描所有竖直的线并标记与它相交的线,保 ...

  3. Educational Codeforces Round 68 E. Count The Rectangles

    Educational Codeforces Round 68 E. Count The Rectangles 传送门 题意: 给出不超过\(n,n\leq 5000\)条直线,问共形成多少个矩形. ...

  4. Codeforces 372 B. Counting Rectangles is Fun

    $ >Codeforces \space 372 B.  Counting Rectangles is Fun<$ 题目大意 : 给出一个 \(n \times m\) 的 \(01\) ...

  5. codeforces 713B B. Searching Rectangles(二分)

    题目链接: B. Searching Rectangles time limit per test 1 second memory limit per test 256 megabytes input ...

  6. codeforces D. Count Good Substrings

    http://codeforces.com/contest/451/problem/D 题意:给你一个字符串,然后找出奇数和偶数长度的子串的个数,这些字串符合,通过一些连续相同的字符合并后是回文串. ...

  7. 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 ...

  8. CodeForces 1216C(假的计算几何+扫描线)

    传送门 •题意 给你三个矩形,依次编号为 1,2,3: 判断 矩形1 是否被 矩形2 和 矩形3 完全覆盖: 如果没有完全覆盖,输出 "YES",反之,输出 "NO&qu ...

  9. Codeforces 1188B - Count Pairs(思维题)

    Codeforces 题面传送门 & 洛谷题面传送门 虽说是一个 D1B,但还是想了我足足 20min,所以还是写篇题解罢( 首先注意到这个式子里涉及两个参数,如果我们选择固定一个并动态维护另 ...

随机推荐

  1. Maya2017下载安装与激活

    目录 1. 更多推荐 2. 下载地址 2.1. OneDrive 2.2. 百度云 3. 安装激活步骤 1. 更多推荐 其他Maya版本的下载与激活:https://www.cnblogs.com/c ...

  2. whetstone

    https://www.cnblogs.com/findumars/p/4173040.html 下载源码:http://www.netlib.org/benchmark/whetstone.c ar ...

  3. mitmproxy 使用mitmdump 过滤请求

    mitmproxy 抓包工具,优点可以使用python进行二次开发,或者进行接口的mock 官网地址:https://www.mitmproxy.org/ 打算用这个最初的需求是,想对app做接口测试 ...

  4. 【leetcode】307. Range Sum Query - Mutable

    题目如下: 解题思路:就三个字-线段树.这个题目是线段树用法最经典的场景. 代码如下: class NumArray(object): def __init__(self, nums): " ...

  5. URLEncode解决url中有特殊字符的问题

      问题:图片上传后的url地址中有&等特殊字符,页面传到后端时被自动处理成了&   解决:前端对url进行URLEncode,后端收到后进行URLDecode   总结:需要在请求u ...

  6. vue对特殊特性的研究

    key 预期:number | string key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes.如果不使用 key,Vue 会使用一种最大限度减少 ...

  7. php implode()函数 语法

    php implode()函数 语法 作用:把数组元素组合为字符串惠州大理石平板 语法:implode(separator,array) 参数: 参数 描述 separator     可选.规定数组 ...

  8. 四-1、Cadence Allegro推荐操作方式和视图命令

    第四章:实用命令详解 1.Cadence Allegro推荐操作方式: 激活命令 选择操作对象的属性 设置相关的命令参数 单击对应的对象 结束命令 2.视图命令:

  9. Jenkins slave-agent.jnlp运行无反应

    在配置Jenkins的Windows节点时候,点击slave-agent.jnlp选择javaws.exe运行无反应,cmd命令执行javaws slave-agent.jnlp也不行,slave-a ...

  10. 170817关于AJAX的知识点

    1.AJAX                  [1] AJAX简介                        全称: Asynchronous JavaScript And XML        ...