C50【模板】可持久化线段树(主席树)P3834 静态区间第 k 小
视频链接:C50【模板】可持久化线段树(主席树)P3834 静态区间第 k 小_哔哩哔哩_bilibili
//权值线段树+离散化+动态开点 nlogn #include <iostream> #include <cstring> #include <algorithm> using namespace std; #define N 200005 #define mid ((l+r)>>1) int n,m,a[N],b[N]; int root[N],tot; //根节点,节点个数 int ls[N*20],rs[N*20],sum[N*20]; //sum:区间数的出现次数之和 void build(int &u,int l,int r){ //建空树 u=++tot; //动态开点 if(l==r)return; build(ls[u],l,mid); build(rs[u],mid+1,r); } void change(int &u,int v,int l,int r,int p){ //点修 u=++tot; //动态开点 ls[u]=ls[v]; rs[u]=rs[v]; sum[u]=sum[v]+1; if(l==r) return; //双指针同步搜索 if(p<=mid) change(ls[u],ls[v],l,mid,p); else change(rs[u],rs[v],mid+1,r,p); } int query(int u,int v,int l,int r,int k){ //点查 if(l==r)return l; //双指针同步搜索 int s=sum[ls[u]]-sum[ls[v]]; if(k<=s)return query(ls[u],ls[v],l,mid,k); else return query(rs[u],rs[v],mid+1,r,k-s); } int main(){ scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) scanf("%d",&a[i]),b[i]=a[i]; sort(b+1,b+n+1); int bn=unique(b+1,b+n+1)-b-1; //去重 // build(root[0],1,bn); for(int i=1; i<=n; i++){ int p=lower_bound(b+1,b+bn+1,a[i])-b; change(root[i],root[i-1],1,bn,p); } while(m--){ int l,r,k; scanf("%d%d%d",&l,&r,&k); int p=query(root[r],root[l-1],1,bn,k); printf("%d\n",b[p]); } return 0; }
//权值线段树+离散化+动态开点 nlogn #include <iostream> #include <cstring> #include <algorithm> using namespace std; #define N 200005 #define ls(u) tr[u].l #define rs(u) tr[u].r #define mid ((l+r)>>1) int n,m,a[N],b[N]; int root[N],tot; //根节点,节点个数 struct tree{ int l,r,sum; //区间数的出现次数之和 }tr[N*20]; void build(int &u,int l,int r){ //建空树 u=++tot; //动态开点 if(l==r) return; build(ls(u),l,mid); build(rs(u),mid+1,r); } void change(int &u,int v,int l,int r,int p){ //点修 u=++tot; //动态开点 tr[u]=tr[v]; tr[u].sum++; if(l==r) return; //双指针同步搜索 if(p<=mid) change(ls(u),ls(v),l,mid,p); else change(rs(u),rs(v),mid+1,r,p); } int query(int u,int v,int l,int r,int k){ //点查 if(l==r) return l; //双指针同步搜索 int s=tr[ls(u)].sum-tr[ls(v)].sum; if(k<=s) return query(ls(u),ls(v),l,mid,k); else return query(rs(u),rs(v),mid+1,r,k-s); } int main(){ scanf("%d%d",&n,&m); for(int i=1; i<=n; i++) scanf("%d",&a[i]), b[i]=a[i]; sort(b+1,b+n+1); int bn=unique(b+1,b+n+1)-b-1; //去重 // build(root[0],1,bn); for(int i=1; i<=n; i++){ int p=lower_bound(b+1,b+bn+1,a[i])-b; change(root[i],root[i-1],1,bn,p); } while(m--){ int l,r,k; scanf("%d%d%d",&l,&r,&k); int p=query(root[r],root[l-1],1,bn,k); printf("%d\n",b[p]); } }
分类:
C 数据结构
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!