UVa12345 Dynamic len(set(a[L:R]))

@[TOC](UVa12345 Dynamic len(set(a[L:R])))

题目链接

  UVA - 12345 Dynamic len(set(a[L:R]))

题意

  有编号从 0 到 n−1 的 n 个数,有两种操作:

  • Q L R 询问编号 L 到编号 R−1 的数中有多少个不同的数字。
  • M X Y 将编号为 X 的数字改为 Y。

  你的任务就是要完成这一系列操作。

输入格式

  输入仅包含一组数据,其中第一行为两个整数 n 和 m(1≤n,m≤50 000),第二行为列表 a 的各个元素值。每个元素都是 111~10610^6106 之间的整数。以下 m 行的格式有两种情况:M x y(1≤y≤1061≤y≤10^61y106)表示执行赋值 a[x]=y;Q x y 表示输出 len(set(a[x:y])) 的值。输入保证不会出现访问越界的情况。

输出格式

  对于每条 Q 指令,输出结果。

分析

  本题可以用分块来做,很多题解说了可以用带修改莫队算法,等掌握了莫队算法再补上来。

分块

  要统计区间 [L,R) 中有多少个不同的数,可以分析一下每个数它前面相同的数在什么位置,可以只统计前面相同的数位置小于 L 的那些数(前面不存在相同数的可以按前面相同的数位置为 -1 处理,自然小于 L)。

  用数组 p[n] 记录每个位置的前一个相同数的位置,初始输入各个元素值时可以初始化 p 数据。取分块大小为 s=ns = \sqrt ns=n,为了后续高效查询,需要给每个块再用一个数组 pre[s] 保存数组 p[n] 中对应块的排序结果。这样在查询时,首尾的块直接在数组 p[n] 中遍历统计,中间哪些块直接对其数组 pre 二分查找小于 L 的有几个就能得到答案,单次查询的时间复杂度为O(nlog⁡n)O(\sqrt n \log \sqrt n)O(nlogn)

  为了满足查询的要求,对每次修改 a[x]=ya[x] = ya[x]=y 的操作,需要更新数组 p 并对相应受影响的分块更新其数组 pre 的排序。不妨再加一个数组 nxt[n] 记录每个位置的后一个相同数的位置(位置 x 不存在后一个相同数时可赋值 next[x] = n)。

  每次修改 a[x]=ya[x] = ya[x]=y 的操作受影响的块最多有三个:旧 nxt[x] 所在的块,因为旧 nxt[x] < n 时会更新 p[ nxt[x] ] = 旧 p[x];x 所在的块,因为会更新 p[x];新 nxt[x] 所在的块,因为新 nxt[x] < n 时会更新 p[ nxt[x] ] = x。

  旧 nxt[x] 的更新容易,难点是更新 p[x] 和新 nxt[x]。考虑对每个块,再维护一个值索引数组 b[s],用于修改 a[x]=ya[x] = ya[x]=y 操作时快速找出位置 x 处的前一个 y 的位置和后一个 y 的位置。举例第一个块(假设 s = 10)如下:

索引0 1 2 3 4 5 6 7 8 9
1 8 7 3 6 4 7 2 1 6
值索引数组 b0 8 7 3 5 4 9 2 6 1

  即值索引数组 b 的排序规则是:若索引 i 对应的值 v[i] 小于 索引 j 对应的值 v[j] 即 v[i] < v[j], 则 i 排在 j 前面;若 v[i] = v[j],则 i < j 时 i 排在 j 前面。有了值索引数组 b,修改 a[x]=ya[x] = ya[x]=y 操作时找位置 x 处的前一个 y 的位置和后一个 y 的位置可以用二分查找。

  对于修改 a[x]=ya[x] = ya[x]=y 操作,找位置 x 处的前一个 y 的位置和后一个 y 的位置的时间复杂度都是 O(nlog⁡n)O(\sqrt n \log \sqrt n)O(nlogn);维护位置 x 所在块的值索引数组 b 排序和维护受影响的最多三个块的 pre 数组排序都可以用插入排序的思想,时间复杂度时 O(log⁡n+n)=O(n)O(\log \sqrt n + \sqrt n) = O(\sqrt n)O(logn+n)=O(n)。因此修改操作整体的时间复杂度是 O(nlog⁡n)O(\sqrt n \log \sqrt n)O(nlogn)

  输入数据时需要初始化数组 p、nxt、pre、b 并对每个分块的 pre、b 数组排序,初始化处理的时间复杂度为 O(nlog⁡n)O(n \log \sqrt n)O(nlogn),单次修改或查询的时间复杂度是 O(nlog⁡n)O(\sqrt n \log \sqrt n)O(nlogn),修改和查询的总次数是 m,因此整个算法的时间复杂度是 O((n+mn)log⁡n)O((n + m\sqrt n) \log \sqrt n)O((n+mn)logn)

  最后,说一个工程实践上的点,c++ STL 的 lower_bound、upper_bound 方法可以传一个自定义比较函数 Compare comp,但是要注意 lower_bound 和 upper_bound 用的比较函数的参数顺序不一样。lower_bound 调用的是 comp(*it, val), 而 upper_bound 调用的是 comp(val, *it)。

带修改莫队算法

  后面补。

AC 代码

分块

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;#define M 1000010
#define N 50010
#define S 224
int a[N], b[N], p[N], q[M], nxt[N], pre[N], m, n;bool cmp(int i, int j) {return a[i] < a[j] || (a[i] == a[j] && i < j);
}bool cmp2(int i, int v) {return a[i] < v;
}bool cmp3(int v, int i) {return v < a[i];
}int get_pre(int x, int y) {if (x % S) {int h = x - x%S, t = min(h+S, n), r = lower_bound(b+h, b+t, y, cmp2) - b;if (r < t && b[r] < x && a[b[r]] == y) {while (++r < t && b[r] < x && a[b[r]] == y);return b[r-1];}x = h;}for (int i = x; i >= S; i -= S) {int r = upper_bound(b+i-S, b+i, y, cmp3) - b - 1;if (b[r] < x && a[b[r]] == y) return b[r];}return -1;
}int get_next(int x, int y) {if (++x % S) {int h = x - x%S, t = min(h+S, n), r = upper_bound(b+h, b+t, y, cmp3) - b - 1;if (b[r] >= x && a[b[r]] == y) {while (--r >= h && b[r] >= x && a[b[r]] == y);return b[r+1];}x = t;}for (int i=x; i<n; i+=S) {int t = min(i+S, n), r = lower_bound(b+i, b+t, y, cmp2) - b;if (r < t && a[b[r]] == y) return b[r];}return n;
}void update_pre(int x, int u) {int h = x - x%S, t = min(h+S, n);if (p[x] > u) {int i = lower_bound(pre+h, pre+t, p[x]) - pre;while (i > h && pre[i-1] > u) pre[i] = pre[i-1], --i;pre[i] = p[x] = u;} else {int i = upper_bound(pre+h, pre+t, p[x]) - pre - 1;while (i+1 < t && pre[i+1] < u) pre[i] = pre[i+1], ++i;pre[i] = p[x] = u;}
}void modify(int x, int y) {if (a[x] == y) return;int u = get_pre(x, y), v = get_next(x, y), h = x - x%S, t = min(h+S, n);int i = lower_bound(b+h, b+t, x, cmp) - b;if (a[x] < y) {while (i+1 < t && (a[b[i+1]] < y || (a[b[i+1]] == y && b[i+1] < x))) b[i] = b[i+1], ++i;b[i] = x;} else {while (i > h && (a[b[i-1]] > y || (a[b[i-1]] == y && b[i-1] > x))) b[i] = b[i-1], --i;b[i] = x;}if (p[x] >= 0) nxt[p[x]] = nxt[x];if (nxt[x] < n) update_pre(nxt[x], p[x]);if (u >= 0) nxt[u] = x;if (v < n) update_pre(v, x);update_pre(x, u); nxt[x] = v; a[x] = y;
}void query(int x, int y) {int cnt = 0, l = x, r = y-1;for (int i = min(l-l%S+S, min(y, n)); l<i; ++l) if (p[l] < x) ++cnt;for (int i = max(r-r%S, l); r >= i; --r) if (p[r] < x) ++cnt;for (int i=l; i<r; i+=S) cnt += lower_bound(pre+i, pre+i+S, x) - pre - i;cout << cnt << endl;
}void solve() {cin >> n >> m; memset(q, -1, sizeof(q));for (int i=0; i<n; ++i) {cin >> a[i]; b[i] = i;if (q[a[i]] >= 0) nxt[q[a[i]]] = i;pre[i] = p[i] = q[a[i]]; nxt[i] = n; q[a[i]] = i;if (i > 0 && i%S == 0) sort(pre+i-S, pre+i), sort(b+i-S, b+i, cmp);}int h = n - (n%S ? n%S : S);sort(pre+h, pre+n); sort(b+h, b+n, cmp);while (m--) {char ch; int x, y; cin >> ch >> x >> y;ch == 'M' ? modify(x, y) : query(x, y);}
}int main() {ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);solve();return 0;
}

带修改莫队算法

  后面补。

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

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

相关文章

[Ubuntu] VNC连接Linux云服务器 | 实现GNOME图形化

将桌面环境修改为 GNOME 并通过 VNC 远程访问的步骤 & TightVNC 的安装与配置说明&#xff1a;1. 安装 GNOME 桌面环境 sudo apt update sudo apt install ubuntu-gnome-desktop -y2. 安装 TightVNC 服务器 sudo apt install tightvncserver -y3. 初始化 VNC Server 并设置…

进程、网络通信方法

一、进程间通信(IPC)方法 适用于同一台主机上的进程间数据交换。 管道(Pipe) 匿名管道:单向通信,仅用于父子进程。 命名管道(FIFO):通过文件系统路径访问,支持无亲缘关系进程。 消息队列(Message Queue) 结构化消息(类型+数据),按类型读取,支持异步通信。…

[激光原理与应用-241]:设计 - 266n皮秒深紫外激光器,哪些因素影响激光器紫外光的输出功率?

一、短期稳定性266nm皮秒深紫外激光器紫外光输出功率的稳定性受非线性晶体性能、光学系统设计、热管理效果、重复频率与脉冲能量匹配度、环境干扰控制等因素影响&#xff0c;具体分析如下&#xff1a;1. 非线性晶体性能晶体选择与状态&#xff1a;BBO&#xff08;偏硼酸钡&…

Django配置sqllite之外的数据库

当连接到其他数据库后端时&#xff0c;如 MariaDB、MySQL、Oracle 或 PostgreSQL&#xff0c;将需要额外的连接参数。请参阅下面的 ENGINE 配置&#xff0c;了解如何指定其他数据库类型。这个例子是针对 PostgreSQL&#xff1a; 在django项目的settings.py文件里&#xff0c;关…

银河通用招人形机器人强化学习算法工程师了

人形强化学习算法工程师&#xff08;26届&#xff09;&#xff08;岗位信息已通过jobleap.cn授权&#xff0c;可在csdn发布&#xff09;银河通用机器人 北京收录时间&#xff1a; 2025年08月11日职位描述1. 研发基于深度强化学习的足式机器人运动控制算法&#xff0c;提升机器…

使用MongoDB存储和计算距离

一、MongoDB 计算距离的优势 优势说明原生地理空间索引支持 2dsphere 索引&#xff0c;高效处理地理坐标查询&#xff08;毫秒级响应&#xff09;。内置地理计算函数提供 $near、$geoWithin、$geoNear 等操作符&#xff0c;无需手动实现复杂计算。高性能基于B树索引优化&#…

鸿蒙开发-ArkUI中@Type作用详细解答

在鸿蒙&#xff08;HarmonyOS&#xff09;应用开发中&#xff0c;Type 是 ArkUI 框架中用于 类型定义和类型检查 的关键注解&#xff08;装饰器&#xff09;。它的主要作用是为自定义组件的属性提供明确的类型约束&#xff0c;确保数据传递的类型安全性。 核心作用解析&#xf…

MCU中的存储器映射(Memory Map)

MCU中的存储器映射(Memory Map) 在MCU(微控制器单元)中,存储器映射(Memory Map)是指将不同类型的存储器(如Flash、RAM、外设寄存器等)和功能模块分配到统一的地址空间的过程。这种映射方式使得CPU可以通过访问特定地址来读写数据或控制外设,而无需关心物理存储介质的…

Rust面试题及详细答案120道(11-18)-- 控制流与函数

《前后端面试题》专栏集合了前后端各个知识模块的面试题&#xff0c;包括html&#xff0c;javascript&#xff0c;css&#xff0c;vue&#xff0c;react&#xff0c;java&#xff0c;Openlayers&#xff0c;leaflet&#xff0c;cesium&#xff0c;mapboxGL&#xff0c;threejs&…

数据结构-排序(2)

一、堆排序 &#xff08;借助树&#xff09;1.利用完全二叉树构建大顶堆 2.堆顶元素和堆底元素进行交换&#xff0c;堆底元素不再参与构建&#xff0c;剩余元素继续构建大顶堆3.时间复杂度 O(nlogn)1.完全二叉树&#xff1a;按照从上到下&#xff0c;从左到右的顺序进行排序2.…

Qt-信号和槽

一.信号和槽概念1. 信号&#xff08;Signal&#xff09;概念&#xff1a;信号是 Qt 对象在状态发生变化或事件发生时自动发出的通知。比如按钮被点击、文本框内容变化、定时器超时等&#xff0c;都会发出相应信号。本质&#xff1a;它只是一个函数声明&#xff08;没有函数体&a…

NLP学习开始-02逻辑回归

逻辑回归什么是逻辑回归逻辑回归的应用场景逻辑回归几个重要概念Sigmoid 函数损失函数构建逻辑回归模型的步骤举个例子参数解释模型优化什么是逻辑回归 逻辑回归&#xff08;Logistic Regression&#xff09;是一种广泛应用于分类问题的统计学习方法&#xff0c;尽管名字中带有…

【运维进阶】LAMPLNMP 最佳实践

LAMP/LNMP 最佳实践 LAMP/LNMP 组件 LAMP&#xff1a;LinuxApacheMysql/MariadbPHP/Python/Perl。 LNMP&#xff1a;LinuxNginxMysql/MariadbPHP/Python/Perl。 Linux&#xff1a;操作系统&#xff0c;提供程序运行基础。Apache/Nginx&#xff1a;Web 服务器&#xff0c;提供网…

深入解析 resolv.conf 文件:DNS 配置的核心

/etc/resolv.conf 文件是 Linux 和类 Unix 系统中 DNS 配置的核心组件。它决定了系统如何将域名解析为 IP 地址&#xff0c;这是网络通信的关键环节。本文将深入探讨 resolv.conf 文件的核心内容&#xff0c;重点讲解 nameserver 指令以及 options 配置中的 attempts 和 rotate…

【LeetCode】102 - 二叉树的层序遍历

题目描述 给你二叉树的根节点 root&#xff0c;返回其节点值的层序遍历&#xff08;即逐层地&#xff0c;从左到右访问所有节点&#xff09;。 解题思路 使用 BFS&#xff08;广度优先搜索&#xff09;的思想&#xff0c;维护当前层的所有节点&#xff0c;逐层处理&#xff1a;…

计算机网络1-5:计算机网络的性能指标

目录 常用性能指标 速率 带宽 吞吐量 时延 时延带宽积 ​往返时间 ​利用率 ​丢包率 常用性能指标 性能指标可以从不同的方面来度量计算机网络的性能 常用的计算机网络的性能指标有8个:速率、带宽、吞吐量、时延、时延带宽积、往返时间、利用率、丢包率 速率 比特…

TDengine IDMP 文档介绍

TDengine IDMP (Industrial Data Management Platform) 是一款 AI 原生的物联网、工业数据管理平台。它通过经典的树状层次结构组织传感器、设备采集的数据&#xff0c;建立数据目录&#xff0c;对数据提供语境化、标准化的处理、并提供实时分析、可视化、事件管理与报警等功能…

使用 iFLOW-CLI GitHub Action 和 Qwen3-Coder 给 GitHub 仓库生成幻灯片风格的文档站点

阿里的心流 https://www.iflow.cn/ 团队最近开源了一款基于终端的 AI Agent 工具 iFLOW CLI, 目前可以免费使用到强大的 Qwen3-Coder、Kimi K2 等模型。又是一款类似 Anthropics Claude Code 的产品。 iFlow CLI 是一款直接在终端中运行的强大 AI 助手。它能够无缝分析代码仓库…

【2025最新】在 macOS 上构建 Flutter iOS 应用

推荐超级课程&#xff1a; 本地离线DeepSeek AI方案部署实战教程【完全版】Docker快速入门到精通Kubernetes入门到大师通关课AWS云服务快速入门实战 目录软件要求操作系统开发工具文本编辑器或集成开发环境安装 Flutter SDK下载并安装 Flutter将 Flutter 添加到您的PATH配置 i…

MySQL 临时表详细说明

目录 MySQL 临时表详细说明 1. 定义 2. 核心特性 3. 创建与使用 4. 典型应用场景 5. 生命周期管理 6. 注意事项 7. 性能优化建议 MySQL 临时表详细说明 1. 定义 临时表是存储在内存或磁盘上的临时性数据表&#xff0c;仅在当前数据库会话中存在。会话结束时自动销毁&a…