POJ 2104 K-th Number

来源:互联网 发布:我的世界js制作器教程 编辑:程序博客网 时间:2024/06/13 14:35

这大概是主席树最经典的一道题了。


首先查询是一个区间,可以联想到前缀和的性质,不如把静态的数列改成动态在末尾添数,利用差分即可查询。

可以离散一下使得树更小一些。

查询时注意大概就是ro节点num减去pre节点num。注意查到的节点是排名,注意在原数组中映射一下。


#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<algorithm>using namespace std;const int maxn=100005;struct tree{int lt,rt,lson,rson,sum;}t[maxn*20];int n,cnt,q;int root[maxn];int a[maxn],b[maxn];void build(int &ro,int l,int r){ro=++cnt;t[ro].lt=l;t[ro].rt=r;if(l==r)return;int mid=(l+r)>>1;build(t[ro].lson,l,mid);build(t[ro].rson,mid+1,r);}void insert(int pre,int &ro,int pos){ro=++cnt;t[ro].lt=t[pre].lt;t[ro].rt=t[pre].rt;t[ro].lson=t[pre].lson;t[ro].rson=t[pre].rson;t[ro].sum=t[pre].sum+1;if(t[ro].lt==t[ro].rt)return;int mid=(t[ro].lt+t[ro].rt)>>1;if(pos<=mid)insert(t[pre].lson,t[ro].lson,pos);else insert(t[pre].rson,t[ro].rson,pos);}int query(int l,int r,int k){if(t[r].lt==t[r].rt)return b[t[r].lt];int sum=t[t[r].lson].sum-t[t[l].lson].sum;if(sum>=k)return query(t[l].lson,t[r].lson,k);else return query(t[l].rson,t[r].rson,k-sum);}int main(){scanf("%d%d",&n,&q);for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];sort(b+1,b+n+1);build(root[0],1,n);for(int i=1;i<=n;i++){int pos=lower_bound(b+1,b+n+1,a[i])-b;insert(root[i-1],root[i],pos);}while(q--){int a,b,c;scanf("%d%d%d",&a,&b,&c);printf("%d\n",query(root[a-1],root[b],c));}}