SS241113C. 数据结构 (struct)

news/2024/11/13 21:23:50/文章来源:https://www.cnblogs.com/liyixin0514/p/18544758

SS241113C. 数据结构 (struct)

题意

\(n\) 个数,\(m\) 个操作,\(n,m,a_i\le 10^6\),每次操作给区间 \([l,r]\) 的所有数字加 \(1\),然后输出全局颜色数量,操作独立

思路

感觉不好想,对我来讲有点难,需要更聪明的脑袋和丰富的想象力。

首先 \(O(n \sqrt{n})\) 的莫队做法是显然的,假设 \(n,m\) 同阶。

考虑从操作出发,操作比较特别,是区间 \(+1\)

那么对于区间每个颜色 \(c\),都会变成 \(c+1\)。此时需要分 \(c\) 是否消失,\(c+1\) 是否新出现讨论。

  1. \(c\) 消失了。

说明所有 \(c\) 都在 \([l,r]\) 内,设 \(mn_c,mx_c\) 分别为 \(c\) 最小、最大出现的位置,即 \(l \le mn_c \le mx_c \le r\)

这个可以扫描线二维数点做,扫描 \(mx_c,r\),数 \(l,mn_c\)

  1. \(c+1\) 新出现了。

计算这个贡献的前提是 \([l,r]\) 中存在 \(c\)

注意因为我们会讨论 \(c+1\) 消失了的情况,并且会计入贡献,因此这里其实是计算在 \([l,r]\) 之外没有 \(c+1\)。如果存在颜色 \(c+1\),则要求 \(l \le mn_{c+1} \le mx_{c+1} \le r\),这个和刚刚一样。另一种情况是本来就不存在颜色 \(c+1\)

简化一下。发现如果操作区间存在 \(c\),且满足 \(c+1\) 全部在操作区间里面,那么原来的 \(c+1\) 就会消失,然后又会有新的 \(c+1\) 出现,因此无需考虑这种情况。而如果本来不存在 \(c+1\),那么也不会有 \(c+1\) 消失的情况。

因此我们要考虑的是:

  1. 操作区间里面没有 \(c\),而 \(c+1\) 全部在操作区间里面,答案减一。
  2. 操作区间里面有 \(c\),而本来不存在 \(c+1\),答案加一。

\([l,r]\) 中不存在 \(c\)。也就是 \([l,r] \subseteq\) 某两个相邻的颜色 \(c\) 之间。

\(pos_l < l \le mn_{c+1} \le mx_{c+1} \le r < pos_r\)。其中 \(pos_l,pos_r\) 表示相邻的两个 \(c\) 的位置。

下面是难点。

扫描 \(r\),扫到 \(mx_{c+1}\) 的时候,在树状数组的 \((pos_l,mn_{c+1}]\) 的位置减 \(1\)(注意区间可能为空集)。扫到 \(pos_r\) 的时候,如果 \(mx_{c+1} \le pos_r\)(注意可以取等,因为等于的时候你之间是减过贡献的,需要加回去),在树状数组的 \((pos_l,mn_{c+1}]\) 的位置加回 \(1\)(注意此时不一定存在 \(c+1\))。

然后你发现操作 \(2\),其实就是当不存在 \(c+1\) 的时候,此时你刚好扫到 \(pos_r\),直接给 \((pos_l,pos_r]\) 加一!

时间复杂度 \(O((n+m) \log n)\)。感觉理解难度比较大。

code

#include<bits/stdc++.h>
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
namespace poetry {#define isdigit(x) (x>='0'&&x<='9')#define gc getchar_unlocked#define pc putchar_unlockedtemplate <typename T>void read(T &x) {x=0;char ch=gc();for(;!isdigit(ch);ch=gc());for(;isdigit(ch);ch=gc()) x=(x<<3)+(x<<1)+(ch^48);}template <typename T>void write(T x,char ch) {static int st[40];int top=0;do {st[top++]=x%10;x/=10;}while(x);while(top) pc(st[--top]^48);pc(ch);}constexpr int N=1e6+7;int n,m;int a[N];int tr[N];int ans[N];void add(int x,int val) { for(;x<=n;x+=x&-x) tr[x]+=val; }int query(int x) {int s=0;for(;x;x-=x&-x) s+=tr[x];return s;}struct que {int id,l,r;}q[N];bool cmp (que a,que b) { return a.r < b.r; }int mx[N],mn[N],mx_pos[N],my_pos[N];int sum;void main() {read(n),read(m);rep(i,1,n) read(a[i]);rep(i,1,m) read(q[i].l),read(q[i].r),q[i].id=i;rep(i,1,n+1) mn[i]=n+1;per(i,n,1) mn[a[i]]=i;rep(i,1,n) my_pos[i]=mx[a[i]], mx_pos[a[i]]=mx[a[i]-1], mx[a[i]]=i;rep(i,1,n) if(mx[i]) sum++;sort(q+1,q+m+1,cmp);int it=0;rep(i,1,m) {int l=q[i].l,r=q[i].r;while(it<r) {++it;if(it==mx[a[it]]) {int L=mx_pos[a[it]], R=mn[a[it]];if(L<R) add(L+1,-1), add(R+1,1);}if(it>=mx[a[it]+1]) {int L=my_pos[it], R=min(it,mn[a[it]+1]);if(L<R) add(L+1,1), add(R+1,-1);}}ans[q[i].id]=query(l);}rep(i,1,m) write(sum+ans[i],'\n');}
}
int main() {#ifdef LOCALfreopen("my.out","w",stdout);#else freopen("struct.in","r",stdin);freopen("struct.out","w",stdout);#endifpoetry :: main();
}

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

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

相关文章

数据类型和运算符

数据类型 动态类型编程语言运行时判断静态类型的编程语言 : Go 、C 、在开发的时候,就需要给一些定义的变量赋值空间大小。C 需要自己去开辟这个空间数据类型 : 每种在Go语言中出现的基本数据类型,会有一个默认的空间大小。 1、布尔类型数据 布尔型的值只可以是常量 true 或…

XXL JOB DockerCompose部署

官网给的方式是 Docker 命令启动,但是用起来太麻烦了,所以用DockerCompose 简化部署 创建数据库,导入 SQL SQL 脚本位置为/xxl-job/doc/db/tables_xxl_job.sql https://raw.githubusercontent.com/xuxueli/xxl-job/refs/heads/master/doc/db/tables_xxl_job.sql 编写 Docker…

CICD02 Jenkins安装,备份还原, 实现CICD核心功能 ubuntu使用

DevOps 之 CICD 服务器 Jenkins 1 Jenkins 部署与基本配置 1.2 Jenkins 安装和启动 1.2.1 Jenkins 的安装 Jenkins支持多种安装方法 1.包安装 2.JAVA的WAR文件 #要手动配置,不太方便 3.容器运行#系统要求 最低推荐配置:1.256MB可用内存2.1GB可用磁盘空间(作为一个Docker容…

CICD01 Git, GitLab, 部署方式 ubuntu使用

版本管理系统 Git 和 GitLab 1 DevOps 简介 1.3 持续集成、持续交付和持续部署 CICD CICD: 持续集成, 持续交付, 持续部署 1.6 常见的软件部署模式 生产中 蓝绿部署 和 金丝雀用的比较多 1.6.1 蓝绿部署 Blue-green Deployments 一个和生产环境一样的预发布环境, 和生产环…

jvm 垃圾回收算法的评价标准

如何实现回收的(核心思想): 1. 找到内存中存活的对象(与GC Root相关联) 2. 释放不再存活对象的内存,使得程序能再次利用这部分空间 --------------------------------------------------------------------------------- 垃圾回收算法的分类: -------- ----------------…

GO面试-切片

一、结构介绍 切片(Slice)在 Go 语言中,有一个很常用的数据结构,切片是一个拥有相同类型元素的可变长度的序列,它是基于数组类型做的一层封装。它非常灵活,支持自动扩容。并发不安全。 切片是一种引用类型,它有三个属性:指针,长度和容量。 底层源码定义: type slice …

系统管理体系——软件包管理

1.Linux系统管理体系——软件包管理Linux下面的软件包格式为:rpm格式(红帽系列系统,CentOS,麒麟系统)或deb格式(Debian,Ubuntu)安装软件方式 举例 说明 应用场景yum/apt 方式 点外卖,缺啥少啥,外卖解 决 通过网络下载软件包,替我们安装, 如果 有依赖自动下载依赖并安装. …

Linux12位权限管理体

1. Linux12位权限管理体 1.1 权限管理概述Linux通过rwx3种权限控制系统与保护系统,组成9位权限. Linux权限体系中还有3位特殊权限,组合起来就是12位权限体系. Linux这简单的rwx控制整个Linux系统的安全,权限与用户共同组成Linux系统的安全防护体系.1.2 Linux权限计算 2.0 rwx权…

Java流程控制(三)

用户交互Scanner(java.util.Scanner获取用户的输入)//基本语法 Scanner s = new Scanner(System.in)通过Scanner类的next()与nextLine()方法获取输入的字符串,使用hasNext()与hasNextLine()判断是否还有输入的数据(Next不能得到带有空格的字符串,NextLine可以获得空白)im…

0.1+0.2=0.30000000000000004

看下效果这个网站能找到你想要的答案 https://0.30000000000000004.com/ 十进制转二进制 十进制整数转换为二进制整数采用"除2取余,逆序排列"法。 具体做法是:用2整除十进制整数,可以得到一个商和余数; 再用2去除商,又会得到一个商和余数,如此进行,直到商为小…

「AT_diverta2019_2_e」Balanced Piles 题解

题意描述 有一个长度为 \(N(2\le N \le 10^6)\) 的数组,一开始所有元素均为 \(0\)。 设 \(M\) 为当前数组中的最大元素,\(m\) 是当前数组中的最小元素,你可以执行若干次以下操作:选择一个大小为 \(m\) 的元素,把他变为 \(x\),其中 \(M\le x \le M+D\) 且 \(m<x\)。 求…

团队项目Scrum冲刺-day3

一、每天举行站立式会议 站立式会议照片一张昨天已完成的工作成员 任务陈国金 用户模块的部分接口凌枫 用户登录页面陈卓恒 用户注册界面谭立业 题目搜索页面部分内容廖俊龙 接口测试曾平凡 前端页面测试曾俊涛 题目模块的部分接口薛秋昊 题目提交模块的部分接口今天计划完成的…