【HT周赛】T3.二维平面 题解(分块:矩形chkmax,求矩形和)

news2025/5/14 13:41:45

题意

需要维护 n × n n \times n n×n 平面上的整点,每个点 ( x , y ) (x, y) (x,y) 有权值 V ( x , y ) V(x, y) V(x,y),初始都为 0 0 0

同时给定 n n n 次修改操作,每次修改给出 x 1 , x 2 , y 1 , y 2 , v x_1, x_2, y_1, y_2, v x1,x2,y1,y2,v,对每个满足 x 1 ≤ x ≤ x 2 , y 1 ≤ y ≤ y 2 x_1 \leq x \leq x_2, y_1 \leq y \leq y_2 x1xx2,y1yy2 ( x , y ) (x, y) (x,y),将 V ( x , y ) V(x, y) V(x,y) 修改为 max ⁡ ( V ( x , y ) , v ) \max(V(x, y), v) max(V(x,y),v)

在所有修改操作进行完后,有 m m m 次查询操作,每次给出 x 1 , x 2 , y 1 , y 2 x_1, x_2, y_1, y_2 x1,x2,y1,y2,查询 ∑ x = x 1 x 2 ∑ y = y 1 y 2 V ( x , y ) \sum\limits_{x = x_1}^{x_2}\sum\limits_{y = y_1}^{y_2} V(x, y) x=x1x2y=y1y2V(x,y)

1 ≤ n , m ≤ 2 × 1 0 5 1 \leq n,m \leq 2 \times 10^5 1n,m2×105
1 ≤ x 1 ≤ x 2 ≤ n , 1 ≤ y 1 ≤ y 2 ≤ n , 1 ≤ v ≤ n 1 \leq x_1 \leq x_2 \leq n, 1 \leq y_1 \leq y_2 \leq n, 1 \leq v \leq n 1x1x2n,1y1y2n,1vn

分析

本题需要我们实现 矩形 c h k m a x chkmax chkmax,求矩形和

首先定义水平方向从左到右 x x x 递增, 竖直方向自上到下 y y y 递增。

一般的 离线矩形操作 是通过 矩形扫描线 解决的。比如 矩形加, 求矩形和,可以通过扫描线维护历史版本和的方法在 O ( n log ⁡ n ) O(n \log n) O(nlogn) 的复杂度内求出答案。但是对于 c h k m a x chkmax chkmax 操作,它很难撤销并且维护矩阵也比较困难。因次矩形扫描线是行不通的。

考虑 分块
具体来说,设阈值为 B B B,将 x x x 轴按照 B B B 为段长分成若干 B × n B \times n B×n 的细长矩形,对这 n B \frac{n}{B} Bn 个细长矩形分别考虑所有修改的影响以及所有查询在这一部分内的答案。

将与当前处理的细长矩形有交的 询问矩形和修改矩形 分成两类: x x x 坐标完全跨过当前矩形的 和 x x x 坐标不完全跨过的。如下图所示:
在这里插入图片描述
在这里插入图片描述

第二类矩形 上下边界的 y y y 坐标取出来进行离散化。那么会得到一个 B × c B \times c B×c 的网格,其中 c c c 表示第二类矩形的数量。

由于一个修改/查询矩形最多会在两个块内作为第二类矩形,因此所有 c c c 的和为 O ( m ) O(m) O(m),得到的总网格数为 O ( B m ) O(Bm) O(Bm)

考虑此时怎么维护修改和查询:对于第二类矩形,修改/查询的范围对应了网格图上的一个矩形。对于第一类矩形,修改/查询的范围对应了离散化前 y y y 坐标上连续的若干行(注意因为我们没有离散化第一类矩形的 y y y 坐标,所以这些 y y y 可能并不能对应网格图上的一个 y ′ y' y)。

由于第一类矩形的存在,仅有一张网格图是不够的。考虑同时维护一个长为 n n n 的数组 A A A 表示将 B B B 列压缩成一列后的每一行。我们希望能够维护出所有修改操作后 网格图上每个格子的权值 以及 A A A 数组每个位置的权值,这样只需要在网格图上求一遍二位前缀和,对 A A A 数组求一遍前缀和,就可以 O ( 1 ) O(1) O(1) 回答出所有询问的答案。

将所有修改矩形按照 v v v 从大到小排序,那么 c h k m a x chkmax chkmax 就变成了覆盖
我们发现所有细长矩形中 网格的总数和 A A A 的长度之和为 O ( B m + n 2 B ) O(Bm + \frac{n^2}{B}) O(Bm+Bn2),取 B = n m B = \frac{n}{\sqrt{m}} B=m n,可以得到 O ( B m + n 2 B ) = O ( n m ) O(Bm + \frac{n^2}{B}) = O(n\sqrt{m}) O(Bm+Bn2)=O(nm ),那么暴力覆盖就是对的。

我们对网格图的 B B B 列维护一个长度为 c c c 的并查集,同时对 A A A 维护一个长为 n n n 的并查集,染色过程中跳过之前已经被染过色的位置。考虑如何计算答案:如果要染色一行,那么我们需要知道这一行对应到的网格图的某一行已经被染色的格子数量,以及覆盖这些格子的权值之和。如果要染色一个格子,我们需要知道这个格子的 y ′ y' y 对应到原来的 y y y 的一段区间中,有多少行已经被染色,以及行染色的权值之和。这些信息都可以在染色一行或一个格子时维护。

最后需要将所有没染色的格子和行求出它们现在的权值和。(因为会受到另一种覆盖的影响)
然后求一遍前缀和即可。复杂度 O ( m n ) O(m\sqrt{n}) O(mn )

// 矩形 chkmax, 矩形求和 
#include<bits/stdc++.h>
#define pb emplace_back
using namespace std;
struct IO{
    static const int S=1<<21;
    char buf[S],*p1,*p2;int st[105],Top;
    ~IO(){clear();}
    inline void clear(){fwrite(buf,1,Top,stdout);Top=0;}
    inline void pc(const char c){Top==S&&(clear(),0);buf[Top++]=c;}
    inline char gc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    inline IO&operator >> (char&x){while(x=gc(),x==' '||x=='\n'||x=='\r');return *this;}
    template<typename T>inline IO&operator >> (T&x){
        x=0;bool f=0;char ch=gc();
       while(!isdigit(ch)){if(ch=='-') f^=1;ch=gc();}
        while(isdigit(ch)) x=(x<<3)+(x<<1)+ch-'0',ch=gc();
        f?x=-x:0;return *this;
    }
    inline IO&operator << (const char c){pc(c);return *this;}
    template<typename T>inline IO&operator << (T x){
        if(x<0) pc('-'),x=-x;
        do{st[++st[0]]=x%10,x/=10;}while(x);
        while(st[0]) pc('0'+st[st[0]--]);return *this;
    }
}fin, fout;
const int N = 2e5 + 10;
const int M = 205;
typedef long long LL;
struct OP {
	int lx, rx, ly, ry, v;
	friend bool operator < (OP a, OP b) {return a.v > b.v;}
} opt[N * 2];
struct Union {
	int n, bin[N];
	int Find(int x) {return x == bin[x] ? x : bin[x] = Find(bin[x]);}
	inline void init(int _n) {n = _n; for(int i = 1; i <= n; i ++ ) bin[i] = i;}
	inline void Merge(int x) {if(x != n) bin[x] = Find(x + 1);}// 将 x 和它的下一个合并 
	inline int nxt(int x) {return Find(x + 1);}
} L[M], U;
int n, m, tmp[N * 2], tot;
int Y[N], bel[N], cnt;
bool exs[N];
LL ans[N], mp[M][N], sum[N], S1[N], C1[N], S2[N], C2[N]; // S1, C1 是网格染色的信息。 S2, C2 是行染色的信息 
inline void solve(int l, int r) { 
	// 首先先把散块修改和询问的 y 坐标离散化	
	vector< int > pos;
	exs[0] = exs[n] = 1; 
	tot = 0; cnt = 0; int st = -1;
	for(int i = 1; i <= n + m; i ++ ) {
		if(opt[i].rx < l || opt[i].lx > r) continue;
		tmp[++ tot] = i;
		if(opt[i].lx <= l && opt[i].rx >= r) ;
		else exs[opt[i].ly - 1] = exs[opt[i].ry] = 1;
		if(opt[i].v == 0) st = (st == -1 ? tot : st);
	}
	if(st == -1) return ;
	int lst = 0;
	for(int i = 0; i <= n; i ++ ) {
		bel[i] = lst;
		if(exs[i]) pos.pb(i), Y[++ cnt] = i, lst ++; // 离散化所有纵坐标 
	}
	for(int i = 1; i <= r - l + 1; i ++ ) L[i].init(cnt); // 第 i 个距离是 Y_{i + 1} - Y_i 
	for(int i = 1; i < cnt; i ++ ) S1[i] = C1[i] = S2[i] = C2[i] = 0;
	U.init(n + 1);
	for(int i = 1; i <= tot; i ++ ) {
		int o = tmp[i];
		if(!opt[o].v) break;
		if(opt[o].lx <= l && opt[o].rx >= r) { // 染一行 
			for(int j = U.Find(opt[o].ly); j <= opt[o].ry; j = U.nxt(j)) {
				sum[j] = S1[bel[j]] + ((r - l + 1) - C1[bel[j]]) * opt[o].v;
				C2[bel[j]] ++; S2[bel[j]] += opt[o].v;
				U.Merge(j);
			}
		}
		else { // 染若干格子 
			for(int x = max(l, opt[o].lx) - l + 1; x <= min(r, opt[o].rx) - l + 1; x ++ ) {
				for(int j = L[x].Find(bel[opt[o].ly]); j <= bel[opt[o].ry]; j = L[x].nxt(j)) {
					mp[x][j] = S2[j] + (Y[j + 1] - Y[j] - C2[j]) * opt[o].v;
					C1[j] ++; S1[j] += opt[o].v;
					L[x].Merge(j);
				}
			}
		}
	}
	// 接下来确定还没染色的所有格子 
	for(int i = 1; i <= r - l + 1; i ++ ) 
		for(int j = 1; j < cnt; j ++ ) {
			if(L[i].Find(j) == j) mp[i][j] = S2[j];
			mp[i][j] = mp[i - 1][j] + mp[i][j - 1] + mp[i][j] - mp[i - 1][j - 1];
		}
	for(int i = 1; i <= n; i ++ ) {
		if(U.Find(i) == i) sum[i] = S1[bel[i]];
		sum[i] += sum[i - 1];
	}	
	for(int i = st; i <= tot; i ++ ) { // 处理所有询问 
		int o = tmp[i];
		if(opt[o].lx <= l && opt[o].rx >= r) ans[o - n] += sum[opt[o].ry] - sum[opt[o].ly - 1];
		else {
			int lx = max(opt[o].lx, l) - l + 1, rx = min(opt[o].rx, r) - l + 1, ly = bel[opt[o].ly], ry = bel[opt[o].ry];
			ans[o - n] += mp[rx][ry] - mp[rx][ly - 1] - mp[lx - 1][ry] + mp[lx - 1][ly - 1];
		}
	}
	for(auto v : pos) exs[v] = 0;
}
int main() {
	fin >> n >> m;
	for(int i = 1; i <= n; i ++ ) 
		fin >> opt[i].lx >> opt[i].rx >> opt[i].ly >> opt[i].ry >> opt[i].v;
	for(int i = 1; i <= m; i ++ ) 
		fin >> opt[i + n].lx >> opt[i + n].rx >> opt[i + n].ly >> opt[i + n].ry;
	stable_sort(opt + 1, opt + n + m + 1);
	int B = min((int)sqrt(n), 200);
	for(int i = 1; i <= n; i += B ) solve(i, min(i + B - 1, n));
	for(int i = 1; i <= m; i ++ ) fout << ans[i], fout.pc('\n');
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2375424.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

qemu热迁移后内存占用突增问题

1.问题描述 虚拟机配置了memoryBackingmemfd的情况下&#xff0c;热迁移虚拟机后&#xff0c;在目的节点 qemu-kvm 进程占用 rss 会突增很多。 如果去掉这个配置没这个现象。 <memoryBacking><source typememfd/> </memoryBacking>2.问题现象 2.1 不配置…

鸿蒙 Core File Kit(文件基础服务)之简单使用文件

查看常用的沙箱目录 应用沙箱文件访问关系图 应用文件目录结构图 查看常用的沙箱目录 Entry Component struct Index {build() {Button(查看常用的沙箱目录).onClick(_>{let ctx getContext() // UI下只能使用这个方法&#xff0c;不能 this.contextconsole.log(--应用缓存…

基于Qt的app开发第七天

写在前面 笔者是大一下计科生&#xff0c;标题这个项目是笔者这个学期的课设&#xff0c;与学长共创&#xff0c;我负责客户端部分&#xff0c;现在已经实现了待办板块的新建、修改。 这个项目目前已经走上正轨了&#xff0c;博主也实现了主要功能的从无到有&#xff…

目标检测任务常用脚本1——将YOLO格式的数据集转换成VOC格式的数据集

在目标检测任务中&#xff0c;不同框架使用的标注格式各不相同。常见的框架中&#xff0c;YOLO 使用 .txt 文件进行标注&#xff0c;而 PASCAL VOC 则使用 .xml 文件。如果你需要将一个 YOLO 格式的数据集转换为 VOC 格式以便适配其他模型&#xff0c;本文提供了一个结构清晰、…

NLTK库: 数据集3-分类与标注语料(Categorized and Tagged Corpora)

NLTK库: 数据集3-分类与标注语料&#xff08;Categorized and Tagged Corpora&#xff09; 1.二分类语料 主要是电影语料&#xff0c;和情绪(积极消极、主观客观)有关&#xff0c;有以下2个语料&#xff1a; 1.1 movie_reviews: IMDb 影评 IMDb&#xff08;Internet Movie …

uni-app学习笔记五-vue3响应式基础

一.使用ref定义响应式变量 在组合式 API 中&#xff0c;推荐使用 ref() 函数来声明响应式状态&#xff0c;ref() 接收参数&#xff0c;并将其包裹在一个带有 .value 属性的 ref 对象中返回 示例代码&#xff1a; <template> <view>{{ num1 }}</view><vi…

ElasticSeach快速上手笔记-入门篇

由来 Elasticsearch 是一个基于 Apache Lucene 构建的分布式、高扩展、近实时的搜索与数据分析引擎&#xff0c;能够高效处理结构化和非结构化数据的全文检索及复杂分析 搜索&#xff0c;即用户在平台如百度进行输入关键词&#xff0c;由后端给出搜索结果数据进行返回&#x…

《ffplay 读线程与解码线程分析:从初始化到 seek 操作,对比视频与音频解码的差异》

1 read-thread 1.1 初始化部分 1.分配. avformat_alloc_context 创建上下⽂ ic avformat_alloc_context();if (!ic) {av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n");ret AVERROR(ENOMEM);goto fail;}2 ic->interrupt_callback.callback deco…

MySQL推荐书单:从入门到精通

给大家介绍一些 MySQL 从入门到精通的经典书单&#xff0c;可以基于不同学习阶段的需求进行选择。 入门 MySQL必知必会 这本书继承了《SQL必知必会》的优点&#xff0c;专门针对 MySQL 用户&#xff0c;没有过多阐述数据库基础理论&#xff0c;而是紧贴实战&#xff0c;直接从…

【Nacos】env NACOS_AUTH_TOKEN must be set with Base64 String.

【Nacos】env NACOS_AUTH_TOKEN must be set with Base64 String. 问题描述 env NACOS_AUTH_TOKEN must be set with Base64 String.原因分析 从错误日志中可以看出&#xff0c;Nacos 启动失败的原因是缺少必要的环境变量 NACOS_AUTH_TOKEN。 NACOS_AUTH_TOKEN: Nacos 用于生…

秋招准备——2.跨时钟相关

格雷码异步FIFO跨时钟域处理 格雷码 一、格雷码规律 相邻性&#xff1a;相邻两个数的格雷码只有一位不同&#xff0c;例如&#xff1a; 0000 → 0001&#xff08;仅最低位变化&#xff09;0001 → 0011&#xff08;仅次低位变化&#xff09;0011 → 0010&#xff08;仅最低位…

激光打印机常见打印故障简单处理意见

一、 问题描述&#xff1a; 给打印机更换新的硒鼓时拉开硒鼓封条时有微量碳粉带出&#xff1b; 原因&#xff1a; 出厂打印测试时&#xff0c;可能会有微量碳粉在磁辊上或者磁辊仓&#xff1b; 解决方法&#xff1a; 擦干净即可正常使用&#xff1b; 二、 问题描述&…

【2025最新】Windows系统装VSCode搭建C/C++开发环境(附带所有安装包)

文章目录 为什么选择VSCode作为C/C开发工具&#xff1f;一、VSCode安装过程&#xff08;超简单&#xff01;&#xff09;二、VSCode中文界面设置&#xff08;再也不用对着英文发愁&#xff01;&#xff09;三、安装C/C插件&#xff08;编程必备神器&#xff01;&#xff09;四、…

MYSQL 查询去除小数位后多余的0

MYSQL 查询去除小数位后多余的0 在MySQL中&#xff0c;有时候我们需要去除存储在数据库中的数字字段小数点后面多余的0。这种情况通常发生在处理金额或其他需要精确小数位的数据时。例如&#xff0c;数据库中存储的是decimal (18,6)类型的数据&#xff0c;但在页面展示时不希望…

基于GF域的多进制QC-LDPC误码率matlab仿真,译码采用EMS算法

目录 1.算法仿真效果 2.算法涉及理论知识概要 3.MATLAB核心程序 4.完整算法代码文件获得 1.算法仿真效果 matlab2022a仿真结果如下&#xff08;完整代码运行后无水印&#xff09;&#xff1a; 本课题实现的是四进制QC-LDPC 仿真操作步骤可参考程序配套的操作视频。 2.算…

Vitrualbox完美显示系统界面(只需三步)

目录 1.使用vitrualbox的增强功能&#xff1a;​编辑 2.安装增强功能&#xff08;安装完后要重启虚拟机&#xff09;&#xff1a; 3. 调整界面尺寸&#xff08;如果一个选项不行的话&#xff0c;就多试试其他不同的百分比&#xff09;&#xff1a; 先看看原来的&#xff0c;…

王炸组合!STL-VMD二次分解 + Informer-LSTM 并行预测模型

往期精彩内容&#xff1a; 单步预测-风速预测模型代码全家桶-CSDN博客 半天入门&#xff01;锂电池剩余寿命预测&#xff08;Python&#xff09;-CSDN博客 超强预测模型&#xff1a;二次分解-组合预测-CSDN博客 VMD CEEMDAN 二次分解&#xff0c;BiLSTM-Attention预测模型…

n8n 修改或者智能体用文档知识库创建pdf

以下是对 Nextcloud、OnlyOffice、Seafile、Etherpad、BookStack 和 Confluence 等本地部署文档协作工具的综合评测、对比分析和使用推荐&#xff0c;帮助您根据不同需求选择合适的解决方案。 &#x1f9f0; 工具功能对比 工具名称核心功能本地部署支持适用场景优势与劣势Next…

论坛系统(中-1)

软件开发 编写公共代码 定义状态码 对执⾏业务处理逻辑过程中可能出现的成功与失败状态做针对性描述(根据需求分析阶段可以遇见的问题提前做出定义)&#xff0c;⽤枚举定义状态码&#xff0c;先定义⼀部分&#xff0c;业务中遇到新的问题再添加 定义状态码如下 状态码类型描…

FPGA+ESP32 = GameBoy 是你的童年吗?

之前介绍的所有的复古游戏机都是基于Intel-Altera FPGA制作的&#xff0c;今天就带来一款基于AMD-Xilinx FPGA的复古掌上游戏机-Game Bub。 Game Bub是一款掌上游戏机&#xff0c;旨在畅玩 Game Boy、Game Boy Color 和 Game Boy Advance 游戏。与大多数现代掌上游戏机一样&…