Luogu P5715 三位数排序
静态查询区间第$k$小数——主席树板子题!
直接上板子即可。
#include<bits/stdc++.h>
#define N 200010
#define mid ((l+r)>>1)
using namespace std;
int n,m,l,r,k,ans,id,siz;
int a[N],b[N];
struct segmenttree {
int ls,rs,sum,root;
}tree[N*40];
void Build(int &o,int l,int r) {
id++;
o=id;
tree[o].sum=0;
if(l==r) {
return;
}
Build(tree[o].ls,l,mid);
Build(tree[o].rs,mid+1,r);
return;
}
void Update(int &o,int l,int r,int pre,int x) {
id++;
o=id;
tree[o].ls=tree[pre].ls;
tree[o].rs=tree[pre].rs;
tree[o].sum=tree[pre].sum+1;
if(l==r) {
return;
}
if(x<=mid) {
Update(tree[o].ls,l,mid,tree[pre].ls,x);
}
else {
Update(tree[o].rs,mid+1,r,tree[pre].rs,x);
}
return;
}
int Find(int x,int y,int l,int r,int k) {
if(l==r) {
return l;
}
int cnt=tree[tree[y].ls].sum-tree[tree[x].ls].sum;
if(k<=cnt) {
return Find(tree[x].ls,tree[y].ls,l,mid,k);
}
else {
return Find(tree[x].rs,tree[y].rs,mid+1,r,k-cnt);
}
}
int main()
{
n=3,m=3;
for(int i=1;i<=n;i++) {
scanf("%d",&a[i]);
b[i]=a[i];
}
sort(b+1,b+n+1);
siz=unique(b+1,b+n+1)-b-1;
Build(tree[0].root,1,siz);
for(int i=1;i<=n;i++) {
int val=lower_bound(b+1,b+siz+1,a[i])-b;
Update(tree[i].root,1,siz,tree[i-1].root,val);
}
l=1,r=n;
for(int i=1;i<=m;i++) {
k=i;
ans=Find(tree[l-1].root,tree[r].root,1,siz,k);
printf("%d ",b[ans]);
}
return 0;
}