数据结构--主席树(不带修改)
主席树原理就是区间内的第k大可以通过每个数字的出现次数随便乱加减搞出来,然后,就可以像前缀和那样建n个线段树,就可以查询区间第k大了!
主要问题就是空间绝对爆炸,大概
看这个图:(来自blog)
可以发现每一颗线段树结构都相同,只是每次都有
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=200001;
int n,m,size,b[maxn],v[maxn],tot,root[maxn];
struct Node{
int l,r,size;
}a[maxn*30];
void build(int l,int r,int &node){
node=++tot;
if(l==r)return;
int mid=l+r>>1;
build(l,mid,a[node].l);
build(mid+1,r,a[node].r);
}
void addtree(int l,int r,int &node,int pre,int x){
node=++tot;
a[node]=a[pre];
a[node].size++;
if(l==r)return;
int mid=l+r>>1;
if(x<=mid)addtree(l,mid,a[node].l,a[pre].l,x);
else addtree(mid+1,r,a[node].r,a[pre].r,x);
}
int query(int l,int r,int lx,int rx,int k){
if(l==r)return l;
int lsize=a[a[rx].l].size-a[a[lx].l].size;
int mid=l+r>>1;
if(k<=lsize)return query(l,mid,a[lx].l,a[rx].l,k);
else return query(mid+1,r,a[lx].r,a[rx].r,k-lsize);
}
inline int hash1(int k){
return lower_bound(b+1,b+size+1,k)-b;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&v[i]);
b[i]=v[i];
}
sort(b+1,b+n+1);
size=unique(b+1,b+n+1)-b-1;
build(1,size,root[0]);
for(int i=1;i<=n;i++){
addtree(1,size,root[i],root[i-1],hash1(v[i]));
}
for(int i=1;i<=m;i++){
int l,r,k;
scanf("%d %d %d",&l,&r,&k);
int x=query(1,size,root[l-1],root[r],k);
printf("%d\n",b[x]);
}
return 0;
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· 语音处理 开源项目 EchoSharp
· 《HelloGitHub》第 106 期
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 使用 Dify + LLM 构建精确任务处理应用