当前位置: 首页 > news >正文

[THUPC 2024 初赛] 二进制 (树状数组单点删除+单点查询)(双堆模拟set)

题解

题目本身不难想

首先注意到所有查询的序列长度都是小于logn级别的

我们可以枚举序列长度len,然后用类似滑动窗口的方法,一次性预处理出每种字串的所有出现位置,也就是开N个set去维护所有的位置。预处理会进行O(logn)轮,每次需要O(n*logn)的时间复杂度初始化set并计算位置。总共复杂度O(nlog^2n),看一下时间限制6s,感觉可以过23333。

删除操作可以直接暴力,直接从每种字串的位置集合中删除所有被影响到的位置,然后再把删除后字符串合并产生的新的子串加入到set中,过程中需要支持O(logn)的单点删除和单点查询。

在set中,删除起始点在L~R之间子串信息,再插入起始点在L到x-1的新构成的子串的信息

删除操作最多O(n/logn)次,每次直接暴力就是O(log^2n),总共复杂度O(nlogn)

接下来就是一些小问题,如何维护单点删除、单点查询的序列呢?

首先我们肯定不会去真正的移动序列,保留原始的输入01序列

可以想到用set去维护当前存在的每个坐标,但是支持查询第k个坐标的话得手写平衡树

也可以想到用线段树或者树状数组维护每个位置的存在信息,在线段树或者树状数组上二分来查询删除后的序列中的第k个坐标的真实位置。

这里使用树状数组

树状数组二分类似于倍增查询LCA的思想,十分易懂。

然后我们迅速写完整个内容,交一发,发现TLE了

看一下复杂度,发现瓶颈在于预处理,于是我们把初始化中对每个位置都进行树状数组二分,替换为直接使用当前位置存在信息数组进行处理,这样预处理中计算坐标的部分就变成O(n)了

但是仍然TLE了

现在瓶颈仍然是预处理,如果C++支持对有序序列O(n)建立set就好了

后来看了洛谷上题解的方法,才知道可以用两个优先队列来模拟set

由于我们只需要维护集合中的最小值以及集合的元素个数

使用两个堆,一个维护插入的内容,另一个维护删除的内容

当查询个数时,两个堆的大小相减即可。当查询最小值时,如果“删除堆”中的最小值与“插入堆”中的最小值相等,就两个一起pop掉,直到找到第一个“插入堆”中存在,但“删除堆”中不存在的元素即可。

(其实也可以用两个vector来模拟,因为对于每种子串,查询的次数只有一次,所以可以大胆排序再查询,这样初始化时间复杂度也是O(nlogn),查询删除子串的总时间复杂度是最坏O(nlog^2n)不过似乎也能过,因为sort在大部分都有序的情况下还是很快的)

改完之后,从6.18s变成了1.17s,发生了质的飞跃23333

有人可能会问,优先队列插入不也是O(logn)的吗,为什么会比set快这么多,因为预处理的过程中插入集合的内容是顺序的,根据小根堆的实现,只有当自己比父亲值小时,才会发生交换,所以在预处理建立小根堆的过程中是O(n)的,这样预处理的总复杂度就变成了O(nlogn),删除方面在理论上最坏时间复杂度也是O(nlog^2n)(假设所有的位置都集中在一种子串上,并且“删除堆”和“插入堆”差不多大)

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<queue>
using namespace std;
#define N 1000005
#define LOG 20
int n, n_real, now;
char ss[N];
// 树状数组维护单点删除与单点查询的序列
// 实际坐标->逻辑坐标(删除后的坐标) getsum
// 逻辑坐标->实际坐标  query   树状数组二分
int tra[N];
int getsum(int x)
{int ret=0;for(;x;x-=x&-x) ret+=tra[x];return ret;
}
void update(int x,int k)
{for(;x<=n;x+=x&-x)tra[x]+=k;
}
int query(int k)// 查询删除后序列的第k位置的实际坐标
{int ans=0,sum=0;for(int i=LOG;i>=0;i--){if(ans+(1<<i)<=n && sum+tra[ans+(1<<i)]<k){sum+=tra[ans+(1<<i)];ans+=(1<<i);}}return ans+1;
}
// a是原始数据,tmp是删除后的数组,b表示当前位是否存在(树状数组建立在b上)
bool a[N],tmp[N],b[N];
int pos[N];
void cal_tmp_all()
{int cnt=0;for(int i=1;i<=n;i++){if(b[i]){pos[++cnt]=i;tmp[cnt]=a[i];}}
}
void cal_tmp(int l,int r)
{l=max(1,l);r=min(r,n_real);for(int i=l;i<=r;i++){pos[i]=query(i);tmp[i]=a[pos[i]];}
}
priority_queue<int,vector<int>,greater<int> > S[N],D[N];
//set<int> S[N];
//set<int>::iterator it;
// 将起始点在l r之间,长度为len的数据加入到set或者从set中删除
void update_set(int l,int r,int len,bool flg)
{r=min(n_real,r+len-1);int lim_l= max(now,1<<(len-1)), lim_r= min(n,(1<<len)-1);int mask=(1<<len)-1;int tmp_value=0;for(int i=l;i<=r;i++){tmp_value=((tmp_value<<1)&mask)|tmp[i];if(i-l+1 >= len && tmp_value>=lim_l && tmp_value<=lim_r){if(flg)S[tmp_value].push(pos[i-len+1]);elseD[tmp_value].push(pos[i-len+1]);}}
}
int main()
{scanf("%d",&n);n_real=n;scanf("%s",ss+1);for(int i=1;i<=n;i++){a[i]=int(ss[i]-'0');update(i,1);b[i]=1;}now=1;for(int len=1;n>>(len-1);len++){cal_tmp_all();update_set(1,n_real,len,1);//printf("start len:%d\n",len);for(;now<(1<<len);now++){//printf("now:%d\n",now);if(now>n)return 0;int siz = (int)S[now].size()-(int)D[now].size();if(!siz){printf("-1 0\n");continue;}while(!S[now].empty()&&!D[now].empty() && S[now].top()==D[now].top()){S[now].pop();D[now].pop();}int x=getsum(S[now].top());printf("%d %d\n",x,siz);int l=max(1,x-len+1),r=min(n_real,x+len-1);// 删除受影响的结果cal_tmp(l,r+len-1);update_set(l,r,len,0);// 删除对应的01序列for(int i=x;i<=r;i++){update(pos[i],-1);b[pos[i]]=0;}n_real-=len;// 添加新产生的序列结果cal_tmp(l,x-1+len-1);update_set(l,x-1,len,1);while(!S[now].empty())S[now].pop();while(!D[now].empty())D[now].pop();}}
}

相关文章:

[THUPC 2024 初赛] 二进制 (树状数组单点删除+单点查询)(双堆模拟set)

题解 题目本身不难想 首先注意到所有查询的序列长度都是小于logn级别的 我们可以枚举序列长度len&#xff0c;然后用类似滑动窗口的方法&#xff0c;一次性预处理出每种字串的所有出现位置&#xff0c;也就是开N个set去维护所有的位置。预处理会进行O(logn)轮&#xff0c;每…...

机器学习算法(11)——集成技术(Boosting——梯度提升)

一、说明 在在这篇文章中&#xff0c;我们学习了另一种称为梯度增强的集成技术。这是我在机器学习算法集成技术文章系列中与bagging一起介绍的一种增强技术。我还讨论了随机森林和 AdaBoost 算法。但在这里我们讨论的是梯度提升&#xff0c;在我们深入研究梯度提升之前&#xf…...

使用GBASE南大通用负载均衡连接池

若要使用负载均衡连接池功能&#xff0c;需要在连接串中配置相关的关键字。有关更详细的关键字信息在 GBASE南大通用 连接参数表‛中介绍。假设存在如下场景&#xff1a;  现有集群中存在 4 个节点&#xff1a; 192.168.9.173, 192.168.9.174, 192.168.9.175, 192.168.9.17…...

Flink 数据序列化

为 Flink 量身定制的序列化框架 大家都知道现在大数据生态非常火&#xff0c;大多数技术组件都是运行在JVM上的&#xff0c;Flink也是运行在JVM上&#xff0c;基于JVM的数据分析引擎都需要将大量的数据存储在内存中&#xff0c;这就不得不面临JVM的一些问题&#xff0c;比如Ja…...

【并发设计模式】聊聊两阶段终止模式如何优雅终止线程

在软件设计中&#xff0c;抽象出了23种设计模式&#xff0c;用以解决对象的创建、组合、使用三种场景。在并发编程中&#xff0c;针对线程的操作&#xff0c;也抽象出对应的并发设计模式。 两阶段终止模式- 优雅停止线程避免共享的设计模式- 只读、Copy-on-write、Thread-Spec…...

Java实现非对称加密【详解】

Java实现非对称加密 1. 简介2. 非对称加密算法--DH&#xff08;密钥交换&#xff09;3. 非对称加密算法--RSA非对称加密算法--EIGamal5. 总结6 案例6.1 案例16.2 案例2 1. 简介 公开密钥密码学&#xff08;英语&#xff1a;Public-key cryptography&#xff09;也称非对称式密…...

simulinkveristandlabview联合仿真——模型导入搭建人机界面

目录 1.软件版本 2.搭建simulink仿真模型 编译错误 3.导入veristand并建立工程 4.veristand导入labview labview显示veristand工程数据 labview设置veristand工程数据 运行labview工程 1.软件版本 matlab2020a&#xff0c;veristand2020 R4&#xff0c;labview2020 SP…...

k8s中Helm工具实践

k8s中Helm工具实践 1&#xff09;安装redis-cluster 先搭建一个NFS的SC&#xff08;只需要SC&#xff0c;不需要pvc&#xff09;&#xff0c;具体步骤此文档不再提供&#xff0c;请参考前面相关章节。 下载redis-cluster的chart包 helm pull bitnami/redis-cluster --untar…...

推荐算法架构7:特征工程(吊打面试官,史上最全!)

系列文章&#xff0c;请多关注 推荐算法架构1&#xff1a;召回 推荐算法架构2&#xff1a;粗排 推荐算法架构3&#xff1a;精排 推荐算法架构4&#xff1a;重排 推荐算法架构5&#xff1a;全链路专项优化 推荐算法架构6&#xff1a;数据样本 推荐算法架构7&#xff1a;特…...

Web前端 ---- 【Vue】vue路由守卫(全局前置路由守卫、全局后置路由守卫、局部路由path守卫、局部路由component守卫)

目录 前言 全局前置路由守卫 全局后置路由守卫 局部路由守卫之path守卫 局部路由守卫之component守卫 前言 本文介绍Vue2最后的知识点&#xff0c;关于vue的路由守卫。也就是鉴权&#xff0c;不是所有的组件任何人都可以访问到的&#xff0c;需要权限&#xff0c;而根据权限…...

uniapp点击tabbar之前做判断

在UniApp中&#xff0c;可以通过监听 tabBar 的 click 事件来在点击 tabBar 前做判断。具体步骤如下&#xff1a; 在 pages.json 文件中配置 tabBar&#xff0c;例如&#xff1a; {"pages":[{"path":"pages/home/home","name":"h…...

DLLNotFoundException:xxx tolua... 错误打印

DLLNotFoundException:xxx tolua... 错误打印 一、DLLNotFoundException介绍二、Plugins文件夹文件目录结构如下&#xff1a; 三、Plugins中的Android文件夹四、Plugins中的IOS文件夹这里不说了没测试过不过原理应该也是选择对应的平台即可五、Plugins中的x86和X86_64文件夹 一…...

Python量化投资——金融数据最佳实践: 使用qteasy+tushare搭建本地金融数据仓库并定期批量更新【附源码】

用qteasytushare实现金融数据本地化存储及访问 目的什么是qteasy什么是tushare为什么要本地化使用qteasy创建本地数据仓库qteasy支持的几种本地化仓库类型配置本地数据仓库配置tushare 的API token 配置本地数据源 —— 用MySQL数据库作为本地数据源下载金融历史数据 数据的定期…...

【投稿】北海 - Rust与面向对象(二)

模板方法 Rust提供了trait&#xff0c;类似于面向对象的接口&#xff0c;不同的是&#xff0c;将传统面向对象的虚函数表从对象中分离出来&#xff0c;trait仍然是一个函数表&#xff0c;只不过是独立的&#xff0c;它的参数self指针可以指向任何实现了该trait的结构。 从对象中…...

HarmonyOS构建第一个ArkTS应用(FA模型)

构建第一个ArkTS应用&#xff08;FA模型&#xff09; 创建ArkTS工程 若首次打开DevEco Studio&#xff0c;请点击Create Project创建工程。如果已经打开了一个工程&#xff0c;请在菜单栏选择File > New > Create Project来创建一个新工程。 选择Application应用开发&a…...

阿里云 ARMS 应用监控重磅支持 Java 21

作者&#xff1a;牧思 & 山猎 前言 今年的 9 月 19 日&#xff0c;作为最新的 LTS (Long Term Support) Java 版本&#xff0c;Java 21 正式 GA&#xff0c;带来了不少重量级的更新&#xff0c;详情请参考 The Arrival of Java 21 [ 1] 。虽然目前 Java 11 和 Java 17 都…...

C++ 类的析构函数和构造函数

构造函数 类的构造函数是类的一种特殊的成员函数&#xff0c;它会在每次创建类的新对象时执行。主要用来在创建对象时初始化对象即为对象成员变量赋初始值。 构造函数的名称与类的名称是完全相同的&#xff0c;并且不会返回任何类型&#xff0c;也不会返回 void。构造函数可用…...

STM32——CAN协议

文章目录 一.CAN协议的基本特点1.1 特点1.2 电平标准1.3 基本的五个帧1.4 数据帧 二.数据帧解析2.1 帧起始和仲裁段2.2 控制段2.3 数据段和CRC段2.4 ACK段和帧结束 三.总线仲裁四.位时序五.STM32CAN控制器原理与配置5.1 STM32CAN控制器介绍5.2 CAN的模式5.3 CAN框图 六 手册寄存…...

数据结构-如何巧妙实现一个栈?逐步解析与代码示例

文章目录 引言1.栈的基本概念2.选择数组还是链表&#xff1f;3. 定义栈结构4.初始化栈5.压栈操作6.弹栈操作7.查看栈顶和判断栈空9.销毁栈操作10.测试并且打印栈内容栈的实际应用结论 引言 栈是一种基本但强大的数据结构&#xff0c;它在许多算法和系统功能中扮演着关键角色。…...

web前端之拖拽API、vue3实现图片上传拖拽排序、拖放、投掷、复制、若依、vuedraggable

MENU vue2html5原生dom原生JavaScript实现跨区域拖放vue2实现跨区域拖放vue2mousedown实现全屏拖动&#xff0c;全屏投掷vue3element-plusvuedraggable实现图片上传拖拽排序vue2transition-group实现拖动排序原生拖拽排序 vue2html5原生dom原生JavaScript实现跨区域拖放 关键代…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法

树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作&#xff0c;无需更改相机配置。但是&#xff0c;一…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

mac:大模型系列测试

0 MAC 前几天经过学生优惠以及国补17K入手了mac studio,然后这两天亲自测试其模型行运用能力如何&#xff0c;是否支持微调、推理速度等能力。下面进入正文。 1 mac 与 unsloth 按照下面的进行安装以及测试&#xff0c;是可以跑通文章里面的代码。训练速度也是很快的。 注意…...

论文阅读:Matting by Generation

今天介绍一篇关于 matting 抠图的文章&#xff0c;抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法&#xff0c;已经有很多的工作和这个任务相关。这两年 diffusion 模型很火&#xff0c;大家又开始用 diffusion 模型做各种 CV 任务了&am…...