简要题意

你需要维护一个长度为 \(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. IDEA中设置背景图片(超详细)

    文章目录 1.效果图 2.详细设置过程 1.效果图 2.详细设置过程

  2. Python基础之模块:3、os模块 sys模块 json模块 json实战

    目录 一.os模块 1.创建目录 2.删除目录 3.查看指定路径下目录内容 4.删除/重命名文件 5.获取/切换当前目录 6.动态获取项目根路径 7.拼接/切割路径 8.判断文件.目录是否存在 9.判 ...

  3. ThreadLocal的使用及原理解析

    # 基本使用 JDK的lang包下提供了ThreadLocal类,我们可以使用它创建一个线程变量,线程变量的作用域仅在于此线程内.<br />用2个示例来展示一下ThreadLocal的用 ...

  4. python的list,dict,set

    list # 1.list() 把可迭代对象转换成list,即for循环遍历的可迭代对象 my_str = "abcdef" new_list = list(my_str) pri ...

  5. 想开发DAYU200,我教你

    摘要:本文主要介绍OpenHarmony富设备DAYU200开发板的入门指导. 本文分享自华为云社区<DAYU200开发指导>,作者: 星辰27. 1 概述 DAYU200开发板属于Ope ...

  6. KatalonRecorder系列(一):基本使用+XPath元素定位

    一.简介 Katalon Recorder是基于selenium的浏览器插件,支持火狐和chrome.可以录制web上的操作并回放,还能导入导出脚本. 二.安装 可在谷歌商店或者火狐附件组件中搜索并选 ...

  7. Java安全之反序列化(1)

    序列化与反序列化 概述 Java序列化是指把Java对象转换为字节序列的过程:这串字符可能被储存/发送到任何需要的位置,在适当的时候,再将它转回原本的 Java 对象,而Java反序列化是指把字节序列 ...

  8. SQLSever数据库基本操作

    一.SQLSever数据库基本操作 1.创建数据库 use master if exists(select * from sysdatabases where name='SMDB') drop da ...

  9. 并发bug之源(二)-有序性

    什么是有序性? 简单来说,假设你写了下面的程序: int a = 1; int b = 2; System.out.println(a); System.out.println(b); 但经过编译器/ ...

  10. .NET周报【11月第3期 2022-11-22】

    国内文章 .NET Conf China 2022 第一批讲师阵容大揭秘!整个期待了! https://mp.weixin.qq.com/s/4p89hhBPw6qv-0OB_T_TOg 目光看过来 ...