题意:
给长度为n的数组和m个区间,求这m个区间中第k小的数。
分析:
数组静态,区间和k动态,划分树的定义题,上模板。
代码:
//poj 2761
//sep9
#include <iostream>
#include <algorithm>
using namespace std;
#define MID(a,b) (a+((b-a)>>1))
const int maxN=100010;
struct Node
{int val[maxN],num[maxN];
};struct Partition_tree
{int n,order[maxN];Node t[20];void init(int len){n=len;for(int i=1;i<=n;++i){scanf("%d",&order[i]);t[0].val[i]=order[i];}sort(order+1,order+1+n);build(1,n,0); } void build(int l,int r,int k){if(l==r) return;int mid=MID(l,r); int lsame=mid-l+1,same=0,ln=l,rn=mid+1;for(int i=l;i<=r;++i)if(t[k].val[i]<order[mid]) --lsame;for(int i=l;i<=r;++i){if(i==l) t[k].num[i]=0;else t[k].num[i]+=t[k].num[i-1]; if(t[k].val[i]<order[mid])t[k].num[i]++,t[k+1].val[ln++]=t[k].val[i];else if(t[k].val[i]>order[mid])t[k+1].val[rn++]=t[k].val[i];else{same++;if(same<=lsame)t[k].num[i]++,t[k+1].val[ln++]=t[k].val[i];else t[k+1].val[rn++]=t[k].val[i];}}build(l,mid,k+1);build(mid+1,r,k+1);}int query(int st,int ed,int x,int l,int r,int k){if(l==r) return t[k].val[l];int lx,ly,rx,ry,mid=MID(l,r);if(st==l) lx=0,ly=t[k].num[ed];else lx=t[k].num[st-1],ly=t[k].num[ed]-t[k].num[st-1];if(ly>=x){st=l+lx;ed=l+lx+ly-1;return query(st,ed,x,l,mid,k+1);}else{rx=st-1-l+1-lx;ry=ed-st+1-ly;st=mid+1+rx;ed=mid+1+rx+ry-1; return query(st,ed,x-ly,mid+1,r,k+1); }}
}tree;int main()
{int n,m;while(scanf("%d%d",&n,&m)==2){tree.init(n);while(m--){int a,b,c;scanf("%d%d%d",&a,&b,&c);printf("%d\n",tree.query(a,b,c,1,n,0));} } return 0;
}