简要题意

你需要维护一个长度为 \(L\) 的序列 \(a\),初始时全部都是 \(0\),有 \(N\) 个操作,支持:

  • C p x,将 \(a_p\) 修改为 \(x\)。
  • Q a b,输出 \([a,b]\) 中的第 \(8\) 大元素的值。

\(1 \leq L,N \leq 10^5\),对于任意时刻,存在 \(0 \leq a_i \leq 10^9\)。

思路

据说这道题有普通线段树的 \(O(N\log N)\) 做法,但我不会,下面介绍一种较为常规的 \(O(N\log^2 N)\) 做法。

首先,看到单点修改区间求第 \(k\) 大元素,你会想到什么。我相信大家的答案都是:树状数组套可持久化权值线段树。但是这玩意太难写,还容易写错。于是我们可以考虑离线算法——整体二分。

先来考虑一个静态版本,即没有修改,你会怎么做?按照常规思路,我们可以在遍历到询问区间 \([L,R]\),值域区间 \([l,r]\) 时。按照询问区间中小于等于 \((l+r)\div 2\) 数的多少分成分两拨,一波小于等于 \(k\)(此时答案小于等于 \((l+r)\div 2\))和大于。然后向下递归。注意查询数的多少可以使用树状数组优化。

如果有修改呢,同样我们应该也把它分成两拨。同样依照整体二分的“值域中点影响”思想,我们可以将修改的值按照 \((l+r)\div 2\) 分成两拨,这样答案就和值域重点有关了。

但是修改会有后效性,我们在处理询问的时候,上一个操作修改的值会影响到当前的操作。我们可以考虑维护两种询问,一种是擦除上一次修改,一种补上这一次修改。两个操作一起加入操作数组,由于顺序性,就可以出色的解决这个问题。

我们分析以下时间复杂度,假设 \(L,N\) 同阶。那么树状数组需要 \(\log N\),询问遍历所有区间 \(N\log N\)(参见调和级数的性质),整体时间复杂度 \(O(N\log^2 N)\)。

另外提一句,这道题是 P2617 Dynamic Rankings 的弱化版。

代码

没有卡常,截止至 \(\text{2022-11-25 12:43:35}\) 位于最优解第三(整体二分比树套树略微慢一点)。

#include <bits/stdc++.h>
#define int long long
using namespace std; int n,m;
const int N = 2e5+5;
int a[N];
namespace BIT{
#define lowbit(x) ((x)&(-(x)))
int t[N];
void update(int p,int v){
while(p<=n){
t[p]+=v;
p+=lowbit(p);
}
}
int query(int p){
int ans=0;
while(p){
ans+=t[p];
p-=lowbit(p);
}
return ans;
}
int query(int l,int r){
return query(r)-query(l-1);
}
} struct Query{
int op,l,r,k,p,v,id;
} q[N]; int ans[N]; void solve(int ql,int qr,int l,int r){
// cout<<ql<<' '<<qr<<' '<<l<<' '<<r<<'\n';
if(ql>qr||l>r){
return;
}
if(l==r){
for(int i=ql;i<=qr;i++){
if(q[i].op==1)ans[q[i].id]=l;
}
return;
}
int mid=(l+r)>>1;
vector<Query> q1,q2;
for(int i=ql;i<=qr;i++){
if(q[i].op==1){
int v=BIT::query(q[i].l,q[i].r);
if(q[i].k<=v){
q2.push_back(q[i]);
}
else{
q[i].k-=v;
q1.push_back(q[i]);
}
}
else{
if(q[i].v<=mid){
q1.push_back(q[i]);
}
else{
BIT::update(q[i].p,q[i].k);
q2.push_back(q[i]);
}
}
}
for(Query i : q2){
if(i.op!=1){
BIT::update(i.p,-i.k);
}
}
for(int i=0;i<(int)q1.size();i++){
q[ql+i]=q1[i];
}
for(int i=0;i<(int)q2.size();i++){
q[ql+q1.size()+i]=q2[i];
}
solve(ql,ql+q1.size()-1,l,mid);
solve(ql+q1.size(),qr,mid+1,r);
} signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>n>>m;
int tot=0;
for(int i=1;i<=m;i++){
char op;int jr,ytxy;
cin>>op>>jr>>ytxy;
if(op=='C'){
if(a[jr]){
q[++tot].op=0;
q[tot].p=jr;
q[tot].v=a[jr];
q[tot].k=-1;
}
q[++tot].op=0;
q[tot].p=jr;
q[tot].v=ytxy;
q[tot].k=1;
a[jr]=ytxy;
}
else{
q[++tot].op=1;
q[tot].l=jr;
q[tot].r=ytxy;
q[tot].k=8;
q[tot].id=i;
}
}
for(int i=1;i<=m;i++)ans[i]=-114514;
solve(1,tot,0,1e9);
for(int i=1;i<=m;i++){
if(ans[i]>=0)cout<<ans[i]<<'\n';
}
return 0;
}

P8701 [蓝桥杯 2019 国 B] 第八大奇迹的更多相关文章

  1. 第十届蓝桥杯2019年C/C++ 大学A组省赛试题

    2019年蓝桥杯第十届软件类省赛 C/C++ 大 学 A 组 试题 A: 平方和 本题总分:5 分 [问题描述] 小明对数位中含有 2.0.1.9 的数字很感兴趣,在 1 到 40 中这样的数包括 1 ...

  2. 第十届蓝桥杯2019年C/C++ 大学B组省赛试题

    2019年第十届蓝桥杯大赛软件类省赛C/C++大学B组 试题 A:组队 本题总分:5分 [问题描述] 作为篮球队教练,你需要从以下名单中选出 1号位至 5号位各一名球员, 组成球队的首发阵容. 每位球 ...

  3. 今日学习——蓝桥杯 2019年 C语言 B组

    1.手淦(亲身体验,,,没啥大用,最终还是代码) 2.代码(下面是我看其他博主代码答案能看的懂的....具体的可以直接去下面的网址看) https://blog.csdn.net/qq_4452491 ...

  4. 蓝桥杯2019初赛]迷宫(dfs版本)

    传送门 大意: 题目的意思还是模板的搜索,不同的是我们要记录路径了,而且是最短字典序最小的路径. 思路: 1.对于字典序最小,也就是说我们要尽量先往下走,然后是左- 这个很简单,因为在dfs中是顺序枚 ...

  5. 平方十位数(蓝桥杯第八届国赛真题 JAVA-B组)

    思路:从大到小枚举,判断其平方是否不重复 答案:9814072356 //水题 标题:平方十位数 由0~9这10个数字不重复.不遗漏,可以组成很多10位数字. 这其中也有很多恰好是平方数(是某个数的平 ...

  6. 2019第十届蓝桥杯省赛及国赛个人总结(java-B组)

    省赛: 今年省赛的题目比18年简单的多,基本都是暴力枚举.BFS之类.还记得去年在山师考蓝桥杯,我这种辣鸡连题目都没看懂.本以为蓝桥会变得越来越难,没想到今年就被打脸了.今年省赛后面三个编程大题一个没 ...

  7. 2019年第十届蓝桥杯国赛总结(JavaA组)

    JavaA组国二,可以报销了~ JA死亡之组可不是盖的,rank12的排名还是拿不到国一啊(只有五个.. 出成绩的一刻波澜不惊,毕竟去年有国一了不慌哈哈哈 不过对我来说这个结果还算意料之外吧,毕竟大三 ...

  8. 2019年第十届蓝桥杯省赛总结(JavaA组)

    //update3.28:省一rank4,莫名进了国赛好神奇.. 记yzm10第一次体验A组(纯粹瞎水). 早闻山东的JavaA组神仙打架,进国赛都成了奢望(往年只有五个名额),因此抱着做分母的心态来 ...

  9. 记 2019蓝桥杯校内预选赛(JAVA组) 赛后总结

    引言 好像博客好久没更新了 哈哈哈哈哈 趁现在有空更新一波 不知道还有没有人看 确实该记录一下每天做了什么了 不然感觉有些浑浑噩噩了 比赛介绍 全称: 蓝桥杯全国软件和信息技术专业人才大赛 蓝桥杯 实 ...

  10. 蓝桥杯第十届真题B组(2019年)

    2019年第十届蓝桥杯大赛软件类省赛C/C++大学B组# 试题 A:组队# 本题总分:5分[问题描述]作为篮球队教练,你需要从以下名单中选出 1号位至 5号位各一名球员,组成球队的首发阵容.每位球员担 ...

随机推荐

  1. 你的哪些骚操作会导致Segmentation Fault😂

    你的哪些骚操作会导致Segmentation Fault 前言 如果你是一个写过一些C程序的同学,那么很大可能你会遇到魔幻的segmentation fault,可能一时间抓耳挠腮,本篇文章主要介绍一 ...

  2. Vue学习之--------组件的基本使用(非单文件组件)(代码实现)(2022/7/22)

    文章目录 1.为啥要使用组件 2.基本使用 3.代码实例 4.测试效果 5.注意点 1.为啥要使用组件 好用啊.像堆积木一样 2.基本使用 Vue中使用组件的三大步骤: 一.定义组件(创建组件) 二. ...

  3. python django搭建一个简易博客的解析(按照文件顺序逐一讲解)

    上次讲解了一下各py文件的内容,但比较乱,所以这次整理了一个顺序版. 源代码请在http://github/Cheng0829/mysite自行下载 mysite: db.sqlite3:数据库文件. ...

  4. Python爬虫urllib库的使用

    urllib 在Python2中,有urllib和urllib2两个库实现请求发送,在Python3中,统一为urllib,是Python内置的HTTP请求库 request:最基本的HTTP请求模块 ...

  5. 一、Go语言开篇介绍

    Go语言开篇介绍 Go语言 是Google公司 在2007开发一种静态强类型.编译型语言,并在 2009 年正式对外发布. Go语言以其近C的执行性能和近解析型语言的开发效率,以及近乎于完美的编译速度 ...

  6. 走进shell

    走进shell 在Linux早起,还没有出现图形化,超哥和其他系统管理员都只能坐在电脑前,输入shell命令,查看控制台的文本输出. 在大多数Linux发行版里,例如centos,可以简单的用组合键来 ...

  7. 分布式事务框架 Seata 入门案例

    1.  Seata Server 部署 Seata分TC.TM和RM三个角色,TC(Server端)为单独服务端部署,TM和RM(Client端)由业务系统集成. 首先,下载最新的安装包 也可以下载源 ...

  8. KMP算法,匹配字符串模板(返回下标)

    //KMP算法,匹配字符串模板 void getNext(int[] next, String t) { int n = next.length; for (int i = 1, j = 0; i & ...

  9. C#实践炸飞机socket通信

    一.前言 最近老师要求做课设,实现一个 "炸飞机" 游戏,我是负责UI界面实现和Socket通信实现的,在这里想总结一下我实现Socket的具体过程,对其中的产生的问题和实现的方法 ...

  10. 更换K8S证书可用期

    帮助文档:https://zealous-cricket-cfa.notion.site/kubeadm-k8s-24611be9607c4b3193012de58860535e 解决: 1.安装GO ...