题目链接:2104 – K-th Number (poj.org)
求解区间第k小的数,这是一道非常版的主席树的题。题意没啥好分析的,主要是谈一下主席树,主席树又叫可持久化线段树,是一种基于差分的数据结构,它的可持久化在于它能够维护它的历史版本,通过两个历史版本的对比差距而来获取这部分的信息。
主席树的大小一般开32倍或者20倍。
#include<bits/stdc++.h>
const int N=1e5+5;
using namespace std;
int n,m,a[N],b[N],tot,T[N*20];
struct node{
int l,r;
int w;
}t[N<<5];
int build(int l,int r){
int p=++tot;
int mid=l+r>>1;
t[p].w=0;
if(l<r){
t[p].l=build(l,mid);
t[p].r=build(mid+1,r);
}
return p;
}
int insert(int pre,int l,int r,int idx,int val){
int p=++tot,mid=l+r>>1;
t[p]=t[pre];
if(l==r){
t[p].w+=val;
return p;
}
if(idx<=mid){
t[p].l=insert(t[pre].l,l,mid,idx,val);
}
else t[p].r=insert(t[pre].r,mid+1,r,idx,val);
t[p].w=t[t[p].l].w+t[t[p].r].w;
return p;
}
int query(int x,int y,int l,int r,int rank){
if(l==r){
return l;
}
int mid=l+r>>1;
if(t[t[y].l].w-t[t[x].l].w>=rank){
return query(t[x].l,t[y].l,l,mid,rank);
}
int tem=rank-t[t[y].l].w+t[t[x].l].w;
return query(t[x].r,t[y].r,mid+1,r,tem);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];
sort(a+1,a+1+n);
T[0]=build(1,n);
for(int i=1;i<=n;i++){
int idx=lower_bound(a+1,a+1+n,b[i])-a;
T[i]=insert(T[i-1],1,n,idx,1);
}
for(int i=1,x,y,z;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
int res=query(T[x-1],T[y],1,n,z);
printf("%d\n",a[res]);
}
return 0;
}
ε=(´ο`*)))唉,再过几天就要去参加上海站了,来复习一下主席树,希望能拿我们学校(acm弱校)今年的第一个铜牌。