矩形有交问题—CDQ
矩阵覆盖问题-CDQ分治
[COCI2018-2019#2] Sunčanje
题目描述
Slavko 做了一个不寻常的梦。在一个晴朗的早上,
日落后,矩形们从屋顶上下来,并睡了一觉。次日,它们发现,有些矩形变成了黄色,而有些仍为白色。变为黄色的矩形都是完全暴露在阳光下的。
请判断每个矩形是否变为了黄色。
输入格式
第一行输入正整数
接下来的
输出格式
输出 DA
,否则在该行输出 NE
。
样例 #1
样例输入 #1
5
1 1 4 2
6 1 1 1
2 2 2 3
3 4 3 2
4 0 1 2
样例输出 #1
NE
DA
NE
DA
DA
样例 #2
样例输入 #2
3
3 3 1 1
2 2 3 3
1 1 5 5
样例输出 #2
NE
NE
DA
提示
样例 1 解释
矩形
数据规模与约定
对于
对于
说明
本题分值按 COCI 原题设置,满分
题目译自 COCI2018-2019 CONTEST #2 T5 Sunčanje。
分析
我们记矩阵序列为
那么矩阵
(在这里有一个细节,就是有可能一个矩形的右边和一个矩形的左边在同一直线上(亦或者一个矩形的上边和一个矩形的下边在同一直线上),但此时没有交点却仍然会被累加进入答案,故为了解决这个问题,可以把右上角整体缩一格,也即右上角的横纵坐标全部-1(这就是部分同志最后几个点过不了的原因));
考虑如何求解
这个玩意类似于偏序问题,考虑使用 CDQ 分治
若按照时间轴分治,则设分治两区间为
此时
此时我们需要考虑后半区间对前半区间的影响,先用常规双指针套路维护限制条件
将区间
采用双指针扫描,则
按照
这里由于限制条件就是要求矩形横向有交点,竖向有交点,而对于竖向有交点,可以转化为线段有交问题,考虑使用维护线段的数据结构——线段树
那,我们对区间
那么就有
统计完了之后将线段树全部清空为-1即可
最后,我们再来梳理一遍这个过程
- 离散化坐标
- 在CDQ分治中
- 左半区间按照
排,右半区间按 排 - 双指针扫描,使得
- 在扫描的过程中不断在线段树的区间
上更新区间最大值 - 对于
查询区间 是否存在大于 的值,存在也就表示 被覆盖 - 清空线段树
时间复杂度是线段树常数大得一批,怪不得时间要求4s
#include<iostream>
#include<cstdio>
#include<algorithm>
#define scanf scanf_s
using namespace std;
#define N 1000050
struct node {
int id, x1, x2, y1, y2;
}a[N];//矩阵
int b[N], c[N], cnt;//离散化
int f[N], n, m;
struct seg_tree {
int mx, tag, lazy, l, r;
}t[N << 2];//线段树
#define lc x<<1
#define rc x<<1|1
void build(int l, int r, int x) {
t[x] = { 0,0,-1,l,r };
if (l == r)return;
int mid = l + r >> 1;
build(l, mid, lc);
build(mid + 1, r, rc);
}
inline void pushup(int x) {
t[x].mx = max(t[lc].mx, t[rc].mx);
}
inline void pushdown(seg_tree& a, seg_tree& b, seg_tree& c) {
if (a.lazy != -1) {
b.tag = c.tag = 0;
b.mx = c.mx = 0;
b.lazy = c.lazy = 0;
a.lazy = -1;
}
b.tag = max(b.tag, a.tag);
c.tag = max(c.tag, a.tag);
b.mx = max(b.mx, a.tag);
c.mx = max(c.mx, a.tag);
a.tag = 0;
return;
}
inline void pushdown(int x) {
pushdown(t[x], t[lc], t[rc]);
}
void update(int x, int l, int r, int k) {
if (l <= t[x].l && t[x].r <= r) {
t[x].mx = max(t[x].mx, k);
t[x].tag = max(t[x].tag, k);
return;
}
pushdown(x);
int mid = t[x].l + t[x].r >> 1;
if (l <= mid)update(lc, l, r, k);
if (mid < r)update(rc, l, r, k);
pushup(x);
}
int find(int x, int l, int r) {
if (l <= t[x].l && t[x].r <= r) {
// printf("%d %d %d %d %d\n", t[x].lazy, t[x].tag, t[x].l, t[x].r, t[x].mx);
return t[x].mx;
}
int ans = -1, mid = t[x].l + t[x].r >> 1;
pushdown(x);
if (l <= mid)ans = max(ans, find(lc, l, r));
if (mid < r)ans = max(ans, find(rc, l, r));
pushup(x);
return ans;
}
#undef lc
#undef rc
void init() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
int A, B, c, d;
scanf("%d%d%d%d", &A, &B, &c, &d);
c += A - 1, d += B - 1;
a[i] = { i,A,c,B,d };
b[++cnt] = A, b[++cnt] = B, b[++cnt] = c, b[++cnt] = d;
}
sort(b + 1, b + cnt + 1);
cnt = unique(b + 1, b + cnt + 1) - b - 1;
// printf("%d\n", cnt);
for (int i = 1; i <= n; i++) {
a[i].x1 = lower_bound(b + 1, b + cnt + 1, a[i].x1) - b;
a[i].y1 = lower_bound(b + 1, b + cnt + 1, a[i].y1) - b;
a[i].x2 = lower_bound(b + 1, b + cnt + 1, a[i].x2) - b;
a[i].y2 = lower_bound(b + 1, b + cnt + 1, a[i].y2) - b;
// printf("%d %d %d %d\n", a[i].x1, a[i].y1, a[i].x2, a[i].y2);
}
}
bool cmp1(node a, node b) {
return a.x1 < b.x1;
}
bool cmp2(node a, node b) {
return a.x2 < b.x2;
}
void cdq(int l, int r) {
if (l == r)return;
int mid = l + r >> 1;
cdq(l, mid);
cdq(mid + 1, r);
int L = l, R = mid + 1;
sort(a + l, a + mid + 1, cmp2);
sort(a + R, a + r + 1, cmp1);
// for (int i = l; i <= r; i++)printf("%d ", a[i].id);
// puts("");
for (; L <= mid; L++) {
while (a[R].x1 <= a[L].x2 && R <= r) {
update(1, a[R].y1, a[R].y2, a[R].x2);
R++;
}
f[a[L].id] |= find(1, a[L].y1, a[L].y2) >= a[L].x1;
// if (find(1, a[L].y1, a[L].y2) >= a[L].x1) {
// printf("%d %d %d\n", a[L].id, find(1, a[L].y1, a[L].y2), L-l);
// }
}
t[1].tag = t[1].mx = t[1].lazy = 0;
pushdown(1);
// puts("Cleaded");
}
int main() {
init();
build(1, cnt << 1, 1);
cdq(1, n);
for (int i = 1; i <= n; i++) {
if (f[i])puts("NE");
else puts("DA");
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!