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]); } }