带修莫队 P1903 题解

news2025/4/8 6:17:05

Part # 0. 前言 \text{Part \# 0. 前言} Part # 0. 前言

这个蒟蒻刚学带修莫队,所以 介绍带修莫队的部分比较简略,大家可以去参考一下 OI-wiki 或者其他大佬的博客:)

本文参考了洛谷题解。

Part # 1. 带修莫队 \text{Part \# 1. 带修莫队} Part # 1. 带修莫队

带修莫队,顾名思义,就是待修改的莫队。

众所周知,普通莫队可以在比较好的时间复杂度内完成一次查询操作,但是不支持修改操作,于是就有了带修莫队。

我们知道,莫队实际上是从[l,r][l+1,r][l-1,r][l,r+1][l,r-1]的转移,而且都是 O ( 1 ) O(1) O(1)的,所以如果我们把中括号改成小括号,那么就是莫队的本质了:
(l,r)->(l-1,r)(l+1,r)(l,r-1)(l,r+1)

在这里插入图片描述
图中四个箭头的移动都是可以 O ( 1 ) O(1) O(1)完成的,那么两点之间的曼哈顿距离就是从一个状态到另一个状态所需要的最小挪动

(不了解曼哈顿距离的同学戳上面加粗字体)

那么对于所有的查询,最快的办法就是在坐标系上找到曼哈顿最小生成树

(其实没有必要会这个因为太麻烦了)

你也许会说:“我不会啊!”

这完全没有关系,因为

我也不会

但是我们并没有必要得到最佳答案,能卡过去就够了。

于是我们采用分块的想法,将其分成(n/sz)个长度为sz的块,在每一个块中按照右端点从小到大来移动

就像这样:

至少这样不会被卡掉……

至于块的大小? n \sqrt n n 呗。

(实际上严谨的说,应该是 n m \dfrac {n}{\sqrt {m}} m n,具体为啥有兴趣的同学可以研究一下,一般来说块的大小 n \sqrt n n 足矣,因此不在此介绍)

那么我们就讲好了本题……的前置部分……

好了!现在我们在这里加入了修改,“我该怎么办呢qwq”

可以这么认为,序列的值是随着时间而变化的

那我们就在坐标系上再加上一个时间维度,用(l,r,t)来表示一个查询

↑大概就是这样

很明显,我们需要分别按照lr分块,在同一块内的询问按照t从小到大完成。块的大小就是 n 2 3 = n 0.6666... {\sqrt [3] {n^{2}}}=n^{0.6666...} 3n2 =n0.6666...

(至于为什么还是看别的题解吧,窝太菜廖)

所以总的来说,只需要在原有的普通莫队上在加一个时间维度就可以了


Code \text{Code} Code

/*
1. sqrt(m*2/3)
*/
#include <bits/stdc++.h>

using namespace std;

#define int long long
#define fi first
#define se second
#define rg register
#define il inline
#define forz(i,a,b) for(register int i((a));i<=(b);++i)
#define forn(i,a,b) for(register int i((a));i>=(b);--i)
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while (ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9') {x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}

inline void write(int x)
{
    if(x<0){putchar('-');x=-x;}
    if(x>9) write(x/10);
    putchar(x%10+'0');
}

const int maxn=2e5+100;
const int mod=993244853;
const int inf=9e18;

int n,m;
int sum;
int sz;
int cntq,cntr;

struct question{
	int l;
	int r;
	int t;
	int id;
}qq[maxn],qr[maxn];

int a[maxn];
int ans[maxn];
int cnt[maxn*10];

inline void add(int x)
{
	sum+= !cnt[x]++;
}

inline void del(int x)
{
	sum-= !--cnt[x];
}

inline void upd(int x,int t)
{
	if(qq[x].l<=qr[t].l&&qr[t].l<=qq[x].r)
	{
		del(a[qr[t].l]);
		add(qr[t].r);
	}
	swap(a[qr[t].l],qr[t].r);
}

bool cmp (const question &a, const question &b)
{
	return a.l / sz == b.l / sz ? a.r / sz == b.r / sz ? a.t < b.t : a.r < b.r : a.l < b.l;
}

inline void solve()
{
	n=read(),m=read();
	sz=pow(n,0.666);
	forz(i,1,n) a[i]=read();
	forz(i,1,m)
	{
		char op;cin>>op;
		int l=read(),r=read();
		if(op=='Q')
		{
			cntq++;
			qq[cntq].id=cntq;
			qq[cntq].l=l;
			qq[cntq].r=r;
			qq[cntq].t=cntr;
		}
		else
		{
			cntr++;
			qr[cntr].l=l;
			qr[cntr].r=r;
		}
	}	
	sort(qq+1,qq+1+cntq,[](const question &a,const question &b){
		return a.l/sz==b.l/sz?a.r/sz==b.r/sz?a.t<b.t:a.r<b.r:a.l<b.l;
	});
	int L=1,R=0,T=0;
	forz(i,1,cntq)
	{	
		while (L>qq[i].l) add(a[--L]);
		while (L<qq[i].l) del(a[L++]);
		while (R>qq[i].r) del(a[R--]);
		while (R<qq[i].r) add(a[++R]);
		while (T<qq[i].t) upd(i,++T);
		while (T>qq[i].t) upd(i,T--);
		ans[qq[i].id]=sum;
	}
	forz(i,1,cntq)
	{
		write(ans[i]);
		putchar('\n');
	}
	putchar('\n');
}

signed main()
{
//    IOS;
	int _=1;
	while (_--) solve();
	return 0;
}

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

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

相关文章

OSPF 路由协议原型系统设计与实现

1.题目描述 参考计算机网络教材 164 页 OSPF 路由协议工作原理&#xff0c;在此基础上&#xff0c;实现一个简单的原型系统。主 要完成工作有&#xff1a;路由节点泛洪发布本地节点的链路信息&#xff0c;其它节点接收信息&#xff0c;构造网络拓扑&#xff0c;然后利 用 Dijk…

Linux第18步_安装“Ubuntu系统下的C语言编译器GCC”

Ubuntu系统没有提供C/C的编译环境&#xff0c;因此还需要手动安装build-essential软件包&#xff0c;它包含了 GNU 编辑器&#xff0c;GNU 调试器&#xff0c;和其他编译软件所必需的开发库和工具。本节用于重点介绍安装“Ubuntu系统下的C语言编译器&#xff27;&#xff23;&a…

如何解决找不到mfc100u.dll无法运行程序问题,分享四种靠谱的方法

在日常使用电脑的过程中&#xff0c;我们可能会遇到各种问题&#xff0c;其中之一就是找不到mfc100u.dll的困扰。这个问题主要是因为mfc100u.dll是Microsoft Foundation Class&#xff08;MFC&#xff09;库中的一个版本特定的DLL文件&#xff0c;它是Visual Studio 2010及更早…

java 音乐会售票平台系统Myeclipse开发mysql数据库struts2结构java编程计算机网页项目

一、源码特点 java 音乐会售票平台系统 是一套完善的web设计系统&#xff0c;对理解JSP java编程开发语言有帮助struts2框架开发mvc模式&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发 环境为TOCAT7.0,Myeclipse8.5开发&#xff0c;数据…

Video classification with UniFormer基于统一分类器的视频分类

本文主要介绍了UniFormer: Unified Transformer for Efficient Spatial-Temporal Representation Learning 代码&#xff1a;https://github.com/Sense-X/UniFormer/tree/main/video_classification UNIFormer 动机 由于视频具有大量的局部冗余和复杂的全局依赖关系&#xf…

企业一线员工定岗定编全解析

引言&#xff1a;在生产制造企业中&#xff0c;由于一线员工工作内容单一&#xff0c;与产量线性关系明显&#xff0c;因此针对一线员工的定编方法最简单有效的就是通过数据计算的方式。人力资源专家——华恒智信根据多年以来对生产制造企业定岗定编的关注与研究得出的经验&…

第7章-第5节-Java中的比较器comparator和泛型的简单说明

1、 引入 上个章节中我们在使用TreeSet保存自定义数据类型的时候&#xff0c;类必须要实现Comparable这个接口&#xff0c;然后重写CompareTo这个方法&#xff0c;这个必须是在具体的自定义类内部去写&#xff0c;有时不方便&#xff0c;每遇到一个都要在那个类内部去写这个Co…

如何把电脑中的项目快速传进Github中?

一、打开GitHub网站:https:github.com 登录自己的个人账号 1.新建一个项目 2.用鼠标直接拖拽电脑中的项目文件夹与文件到新创建的项目中点击保存即可。

Xfs文件系统磁盘布局

目录 一&#xff0c;CentOS下Xfs文件系统的安装 二&#xff0c;准备工作 三&#xff0c;AG结构 四&#xff0c;AG超级块 五&#xff0c;AG空闲磁盘空间管理 六&#xff0c;ABTB的Btree 七&#xff0c;ABTB/ABTC的节点块管理 八&#xff0c;inode节点管理 九&#xff0…

Redis 键中冒号的用途是什么?可以使匹配查询更快吗?

Redis 键中冒号的用途是什么在Redis中&#xff0c;冒号&#xff08;:&#xff09;用作键的分隔符&#xff0c;它的主要作用是创建层次结构和命名空间。通过在键中使用冒号&#xff0c;可以将键分为多个部分&#xff0c;从而更好地组织和管理数据。 以下是冒号在Redis键中的用途…

PyTorch|构建自己的卷积神经网络——卷积层

在构建我们的网络时&#xff0c;我们需要用到卷积层提取特征&#xff0c;来看到一些特别的东西&#xff0c;当图片经过卷积层&#xff0c;图片尺寸一般会变化。 当我们构建网络时&#xff0c;我们需要确定各个层的参数&#xff0c;而这些参数&#xff0c;则是要提前计算的&…

【Python常用函数】一文让你彻底掌握Python中的numpy.append函数

大数据时代的到来,使得很多工作都需要进行数据挖掘,从而发现更多有利的规律,或规避风险,或发现商业价值。而大数据分析的基础是学好编程语言。本文和你一起来探索Python中的append函数,让你以最短的时间明白这个函数的原理。也可以利用碎片化的时间巩固这个函数,让你在处…

【数据分享】2024年我国主要城市地铁站点和线路数据

地铁站点与线路数据是我们经常会用到的一种基础数据。去哪里获取该数据呢&#xff1f; 今天我们就给大家分享一份2024年1月采集的全国有地铁城市的地铁站点与线路数据&#xff0c;数据格式为shp&#xff0c;数据坐标为wgs1984地理坐标。数据中不仅包括地铁&#xff0c;也包括轻…

软件测试|深入理解SQL RIGHT JOIN:语法、用法及示例解析

引言 在SQL中&#xff0c;JOIN是一种重要的操作&#xff0c;用于将两个或多个表中的数据关联在一起。SQL提供了多种JOIN类型&#xff0c;其中之一是RIGHT JOIN。RIGHT JOIN用于从右表中选择所有记录&#xff0c;并将其与左表中匹配的记录组合在一起。本文将深入探讨SQL RIGHT …

x-cmd pkg | you-get - web 媒体内容下载工具

目录 简介首次用户功能特点竞品和相关作品进一步阅读 简介 You-Get 是一个开源的命令行小型下载工具&#xff0c;用于从各种网站下载视频、音频和其他媒体文件。 它可以解析和下载嵌套在网页中的媒体&#xff0c;能从 YouTube、优酷、Niconico 、bilibili 等热门网站下载视频、…

leetcode:1108. IP 地址无效化

一、题目 二、函数原型 char* defangIPaddr(char* address) 三、思路 本题通俗来讲就是将字符串中的 . 替换为 [.] 先遍历字符串得出有num个 . 且申请 len 2*num 1 个char空间ans。len是原字符串长度&#xff0c;2*num是[ ]的个数&#xff0c;1是 ‘ \0 ’ 的空间。 …

STL——vector详解

目录 &#x1f4a1;基本概念 &#x1f4a1;存放内置数据类型 &#x1f4a1;存放自定义数据类型 &#x1f4a1;存放自定义数据类型指针 &#x1f4a1;vector容器嵌套容器 &#x1f4a1;vector构造函数 &#x1f4a1;vector赋值操作 &#x1f4a1;vector容量和大小 &…

Linux基础命令@grep、wc、管道符

目录 grep概念语法作用演示一演示二演示三&#xff0c;带选项 -n wc概念语法作用wc&#xff0c;不带选项-c&#xff0c;统计字节数-m&#xff0c;统计字符数-l&#xff0c;统计行数-w&#xff0c;统计单词数 管道符语法作用演示一演示二演示三演示四演示五 总结 grep 概念 gre…

十一、工具盒类(MyQQ)(Qt5 GUI系列)

目录 ​编辑 一、设计需求 二、实现代码 三、代码解析 四、总结 一、设计需求 抽屉效果是软件界面设计中的一种常用形式&#xff0c;可以以一种动态直观的方式在有限大小的界面上扩展出更多的功能。本例要求实现类似 QQ 抽屉效果。 二、实现代码 #include "dialog.…

web前端开发技术复习问答题

目录 1.简述常见单标签和双标签有哪些&#xff1f; 2.常见块级元素和行级元素有哪些&#xff1f; 3.简述常见的列表有哪些&#xff1f;他们有什么区别&#xff1f; 4.简述超链接的href属性值如何设置&#xff1f;有什么区别 5.CSS基本语法 6. css中常见的引入方式有几种&…