划分树 hdu2665 第k小

来源:互联网 发布:德国拜发测毒素软件 编辑:程序博客网 时间:2024/05/17 22:31

           题目链接:点击打开链接

            题意有点问题,应该是第k小。其实题不难,就是模板题。

            刚学了划分树,留个模板。

           详细代码:

         

#include <stdio.h>#include <iostream>#include <string.h>#include <algorithm>#include <math.h>using namespace std;const int maxn = 1e5+100;int Tree[30][maxn];int num[30][maxn];int Sorted[maxn];void Build(int l,int r,int rt){if(l==r) return ;int mid=(l+r)>>1;int n=mid-l+1;int i;for(i=l;i<=r;i++){if(Tree[rt][i]<Sorted[mid]) n--;}int L=l;int R=mid+1;for(i=l;i<=r;i++){if(Tree[rt][i]<Sorted[mid]){Tree[rt+1][L++]=Tree[rt][i];}else if(Tree[rt][i]==Sorted[mid] && n>0 ){n--;Tree[rt+1][L++]=Tree[rt][i];}else Tree[rt+1][R++]=Tree[rt][i];num[rt][i]=num[rt][l-1]+L-l;}Build(l,mid,rt+1);Build(mid+1,r,rt+1);}int query(int L,int R,int k,int l,int r,int rt)//L,R为查询区间{if(L==R) return Tree[rt][L];int mid=(l+r)>>1;int cnt=num[rt][R]-num[rt][L-1];if(cnt>=k){ int newl=l+num[rt][L-1]-num[rt][l-1];int newr=l+num[rt][R]-num[rt][l-1]-1;return query(newl,newr,k,l,mid,rt+1);}else{int newl=mid+L-l+1-(num[rt][L-1]-num[rt][l-1]);int newr=mid+R-l+1-(num[rt][R]-num[rt][l-1]);return query(newl,newr,k-cnt,mid+1,r,rt+1);}}int main(){int t;scanf("%d",&t);while(t--){int n,m;memset(Tree,0,sizeof(Tree));memset(num,0,sizeof(num));int i,j,k;scanf("%d%d",&n,&m);for(i=1;i<=n;i++){scanf("%d",&Tree[0][i]);Sorted[i]=Tree[0][i];}sort(Sorted+1,Sorted+n+1);int L,R;Build(1,n,0);while(m--){scanf("%d%d%d",&L,&R,&k);printf("%d\n",query(L,R,k,1,n,0));}}return 0;}



0 0