块状链表的超高速实现
很久以前写的文章了,有空补一下。
块状链表是什么,这是一个可以用来代替平衡树的东西。平衡树一般很长,作为手残选手,自然不可能像lxl那样快速的3分钟打完平衡树。
但是有了块状链表就不一样,这个东西可以让你也3分钟写完块状链表。
块状链表是用分块套链表实现的。但是我并没写过这个东西,我是根据w33z的日报去写的。为啥?我写的链表很丑。
有一个好东西叫作 ,我们都知道的是 中也有一个叫做插入的东西。具体的来说是怎么做的呢?就是下面这样:v.insert(v.begin()+x,y)
表示的就是在第x个位置哪里插入一个值为 的数。
另外的,他还可以支持删除操作与修改操作,所以这让我们感觉到这就像是一个链表一样。但实际他的复杂度还是为 的。
我们考虑去优化这个东西,优化这个东西,那我们就是要把这个 中所保存的数量变小,这样就会让他看起来比较友好。这让我们想到了分块。
具体怎么做?建立多个 来表示一段序列。
每个 中保存的数不超过 ,那么总体就有 个 。
建立出 之后还有一些很不错的运用。
区间第k大查询
插入与删除一个数
单点修改,区间修改(再套一个分块)
我们如果将 。
那么可以证明的是总复杂度其实是约为 的。
接下来先看一道例题。
【分析】
这里可以直接维护一堆 ,然后大力插入查找。
为了保证我们复杂度的优秀,当某一块的元素为选定 的大小
两倍多时,考虑 重构块。看着很不优秀,但是复杂度很不错。
因为设块长为 时,必须插入
个数才会重构一次。而最多全是插入操作时,就会重构 次,于是复杂度就是铁打不动的
【代码】
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5;
int n,bel,tmp[N],x;
const int siz=300;
vector<int>v[N];
vector<int>::iterator it;
int fin(int &kth){
for(int i=1;i<=bel;i++){
kth-=v[i].size();
if(kth<=0){kth+=v[i].size();return i;}
}
}
void rebuild(){
int tot=0;
for(int i=1;i<=bel;i++){
for(it=v[i].begin();it!=v[i].end();it++) tmp[++tot]=*it;
v[i].clear();
}
for(int i=1;i<=tot;i++){bel=(i-1)/siz+1;v[bel].push_back(tmp[i]);}
}
void insert(int p,int val){
int id=fin(p);v[id].insert(v[id].begin()+p-1,val);
if(v[id].size()>2*siz) rebuild();
}
signed main(){
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n;
for(int i=1;i<=n;i++){
cin>>x;bel=(i-1)/siz+1;
v[bel].push_back(x);
}
for(int i=1;i<=n;i++){
int op,l,r,c;cin>>op>>l>>r>>c;
if(!op){insert(l,r);}
else{int id=fin(r); cout<<v[id][r-1]<<"\n";}
}
return 0;
}
然后我们发现我们甚至没有怎么压行,还是很短,只有37行。我写这段代码只用了6分钟。练习一下就可以进步到4分钟左右。
然后神仙 的代码...还是跳过吧
因为 不支持
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下