P1486 [NOI2004] 郁闷的出纳员

news/2025/1/21 20:10:52/文章来源:https://www.cnblogs.com/XichenOC/p/18684363

P1486 [NOI2004] 郁闷的出纳员

题目翻译:

维护一个可重数集,共有 \(n\) 次操作,和一个最小限制 \(min\),共有四种操作:

  • \(I\) \(k\) 给集合添加 \(k\)\(k<min\) 则直接删除(不算入删除个数)
  • \(A\) \(k\) 将集合中的所有元素加上 \(k\)
  • \(S\) \(k\) 将所有元素减少 \(k\) 并将所有值小于 \(min\) 的删除
  • \(F\) \(k\) 输出集合中元素从大到小的第 \(k\) 名的值,若 \(k\) 大于当前元素的值,则输出 \(-1\)

最后还要输出总共删除了多少元素

思路:

对于求第 \(k\) 大的数和随时可以插入等操作,很容易想到用平衡树来维护。由于可能会有重复的数,我们可以给每个节点都维护一个 \(cnt\) 用来储存该节点数的个数。

  • 对于插入操作就与普通的插入没有区别,只要特判一下,看是否有一样的,有就直接给该节点加一。并且要特判一下是否小于 \(min\),若小于则直接跳过。
void ins(int key){if(key<mi)return;int now=rt,f=0;while(now && tr[now].key!=key){f=now;now=tr[now].s[key>tr[now].key];}if(now){tr[now].cnt++;splay(now); return;}now=newnode(key);fa(now)=f;if(f)tr[f].s[key>tr[f].key]=now;splay(now);
}
  • 对于给所有加上 \(k\)我们可以暴力的给所有节点都加上 \(k\),不管是否已经删除或者有没有用,应为删除的节点已经没有与树有连边,所以无法访问,自然没有影响,时间复杂度为 \(O(n)\)
for(int i=1;i<=idx;i++){tr[i].key+=k;
}
  • 对于对所有节点减去 \(k\),我们也可以全部减去,但为了删点,我们可以先找到最接近且 \(\geq k+min\) 的点,将他给 \(splay\) 到根节点,这样所有减去 \(k\) 会小于 \(min\) 的节点都会在根节点的左子树,这样只需要给 \(ans\) 加上子树大小,然后断开连接即可。最后给所有节点减去 \(k\).
void find(int key){int now=rt;while(key!=tr[now].key && tr[now].s[key>tr[now].key]){now=tr[now].s[key>tr[now].key];}splay(now);
}
int nxt(int key){find(key);if(tr[rt].key>=key)return rt;int now=rc(rt);while(lc(now))now=lc(now);return now;
}
void del2(int x){int now=nxt(x+mi);splay(now);ans+=tr[lc(now)].siz;lc(now)=0;pushup(now);for(int i=1;i<=idx;i++){tr[i].key-=x;}
}
  • 查找第 \(k\) 大的数。与普通查找没有什么区别但要注意的是,由于为了防止树中没有符合要求的节点,所以会先加入一个极大值,所以找的时候要找第 \(k+1\) 大的数。其次,由于有重复的数,所以在转移时还会要算上 \(cnt\)
int kth(int rk){int now=rt;if(rk>=tr[now].siz)return -1;rk++;while(true){int sz=tr[rc(now)].siz;if(sz>=rk && rc(now)){now=rc(now);}else if(rk>tr[rc(now)].siz+tr[now].cnt){rk-=sz+tr[now].cnt;now=lc(now);}else{return tr[now].key;}}
}

完整代码:

#include<bits/stdc++.h>
#define lc(x) tr[(x)].s[0]
#define rc(x) tr[(x)].s[1]
#define fa(x) tr[(x)].fa
using namespace std;
const int N=3e5+10;
struct tree{int s[2],fa,siz,key,cnt;tree(){s[0]=s[1]=fa=siz=cnt=key=0;}
}tr[N];
int idx,rt,mi,ans;
void pushup(int x){tr[x].siz=tr[lc(x)].siz+tr[rc(x)].siz+tr[x].cnt;
}
void clear(int x){lc(x)=rc(x)=fa(x)=tr[x].siz=tr[x].key=tr[x].cnt=0;
}
int newnode(int key){tr[++idx].key=key;tr[idx].siz=1;tr[idx].cnt=1;return idx;
}
int get(int x){return x==rc(fa(x));
}
void rotate(int x){int y=fa(x),z=fa(y),c=get(x);if(tr[x].s[c^1])fa(tr[x].s[c^1])=y;tr[y].s[c]=tr[x].s[c^1];tr[x].s[c^1]=y;fa(y)=x;fa(x)=z;if(z)tr[z].s[y==rc(z)]=x;pushup(y);pushup(x);
}
void splay(int x){for(int f=fa(x);f=fa(x),f;rotate(x)){if(fa(f))rotate(get(x)==get(f)?f:x);}rt=x;
}
void ins(int key){if(key<mi)return;int now=rt,f=0;while(now && tr[now].key!=key){f=now;now=tr[now].s[key>tr[now].key];}if(now){tr[now].cnt++;splay(now); return;}now=newnode(key);fa(now)=f;if(f)tr[f].s[key>tr[f].key]=now;splay(now);
}
int kth(int rk){int now=rt;if(rk>=tr[now].siz)return -1;rk++;while(true){int sz=tr[rc(now)].siz;if(sz>=rk && rc(now)){now=rc(now);}else if(rk>tr[rc(now)].siz+tr[now].cnt){rk-=sz+tr[now].cnt;now=lc(now);}else{return tr[now].key;}}
}
void find(int key){int now=rt;while(key!=tr[now].key && tr[now].s[key>tr[now].key]){now=tr[now].s[key>tr[now].key];}splay(now);
}
int nxt(int key){find(key);if(tr[rt].key>=key)return rt;int now=rc(rt);while(lc(now))now=lc(now);return now;
}
void del2(int x){int now=nxt(x+mi);splay(now);ans+=tr[lc(now)].siz;lc(now)=0;pushup(now);for(int i=1;i<=idx;i++){tr[i].key-=x;}
}
int main(){int n;scanf("%d%d",&n,&mi);ins(1547483647);for(int i=1;i<=n;i++){char op;int k;cin>>op>>k;if(op=='I'){ins(k);}if(op=='A'){for(int i=1;i<=idx;i++){tr[i].key+=k;}}if(op=='S'){del2(k);}if(op=='F'){printf("%d\n",kth(k));}}printf("%d\n",ans);
}

平衡树讲解

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

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

相关文章

图片内存变大

平时我们会经常遇到压缩图片内存的情况,但是需要把图片内存变大的情况有人遇到过吗,接下来就是图片变大术的详细教程!将需要处理的图片放在一个文件夹内(例:图片a.png放在D盘根目录下)win+R输入cmd打开命令控制行在命令控制行输入cd+图片所在的目录,如果是在磁盘根目录直…

paddleocr图片文字识别

介绍:PaddleOCR是由百度开发的一个OCR库,基于深度学习框架PaddlePaddle。PaddleOCR支持多语言文本识别,特别适合中文场景,同时它还提供了丰富的预训练模型。 1、安装pip3 install paddlepaddle pip3 install paddleocr2、使用from paddleocr import PaddleOCRdef paddle_im…

picoctf_2018_rop chain

main里面有个gets溢出函数,再点开flag函数看可以看到传入了一个a1参数,如果win1和win2都是1且a1为-559039827时会输出flag的值用十六进制比较,该数的十六进制可以直接再ida里面看到看到win1函数设置了win1为1,win2函数需要再传入一个参数为-1163220307那么win2就是1了这个参…

whuwc 游记

whuwc 游记whuwc 游记Star Sky Here we are 我们在此地 Riding the sky 翱翔于天际 Painting the night with sun 绘夜空以晨旭 You and I, Mirrors of night 你和我 交相辉映 Twin flames of fire 如两团火焰 Lit in another time and place 闪亮在彼时彼地 I knew your name …

nvm自动切换node版本

1、nvm常用命令nvm off //禁用node.js版本管理(不卸载任何东西) nvm on //启用node.js版本管理 nvm install <version> //安装node.js的命名 version是版本号 例如:nvm install 8.12.0 nvm uninstall <version> …

业财一体化与业财融合的联系与区别

业财一体化与业财融合比较相似,许多人把二者混为一谈,甚至概念搞反了,他俩有何异同呢?1 从定义来看,业财一体化(Integrated Business and Finance)是指将企业的业务活动与财务活动进行信息化、系统化的统一管理,通过先进技术手段,将业务流程、财务流程、管理流程有机整…

[docker] 部署 Seata 分布式事务

docker 部署 Seata 分布式事务在使用 Docker 部署 Seata 并与 Nacos 配置中心结合时,你可以通过以下步骤来实现。Seata 是一个开源的分布式事务解决方案,而 Nacos 是阿里巴巴开源的一个动态服务发现、配置和服务管理平台。 一、环境准备部署好 mysql 服务 部署好 nacos 服务二…

微信 Callkit 扩大测试范围;DeepSeek-R1 模型发布,性能对标 OpenAI o1 正式版丨 RTE 开发者日报

开发者朋友们大家好:这里是 「RTE 开发者日报」 ,每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE(Real-Time Engagement) 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文章 」、「有看点的 会议 」,但内容仅代表编辑…

《操作系统真象还原》第九章 线程(一) 在内核中实现线程

本文是对《操作系统真象还原》第九章(一)学习的笔记,欢迎大家一起交流。第九章 线程(一) 在内核中实现线程 本文是对《操作系统真象还原》第九章(一)学习的笔记,欢迎大家一起交流。 我们在本节的任务:创建并初始化PCB 模拟pthread_create函数创建线程并执行线程函数首…

1.21 javaweb学习

今天学习了html中onsubmit的使用 onsubmit事件处理器是专门用于表单(form)的提交事件,所以要注意div标签是不能直接使用onsubmit的 今天在作业项目中出现了这样的问题,将onsubmit放在了div标签中,导致数据无法被正常处理,上传数据有误,修改至form后问题解决 修改前数据提…

思通数科舆情系统的分析报告主要内容及其市场价值探析

思通数科舆情系统的分析报告广泛应用于以下几个领域: (1) 企业品牌管理与危机预警:系统能够自动发出警报,为企业的公关部门提供应对策略和决策依据,帮助企业迅速做出反应,避免危机的进一步扩展。 (2) 政府舆情监管与社会治理:政府部门能够利用该系统的热点事件排名、舆情…

北汇信息致客户的一封感谢信

北汇信息致客户的一封感谢信尊敬的客户:感谢您选择北汇信息!2024年是不平凡的一年,中国汽车产量再创新高,出海与内卷挑战不断。北汇信息作为汽车电子测试领域的服务商,秉承“价值创造、共享成功”的理念,一直致力于为国内外汽车客户提供优质的产品和服务,共同面对这些挑…