hdu 2665 裸的划分树

#include<stdio.h>
#include<algorithm>
#define N 100100
using namespace std;
struct node
{
    int x,y,mid;
}a[N*4];
struct Tree
{
    int val,num,p;
}tree[20][N];
int st[N];
void build(int x,int y,int cen,int t)
{
    int m,v;
    a[t].x=x; a[t].y=y; m=a[t].mid=(x+y)>>1;
    Tree *last=tree[cen-1],*cur=tree[cen];
   int mid=st[m],sum=0,i,l=x,r=m+1;
   for(i=m;i>=x;i--)
   {
       if(st[i]==mid)
          sum++;
       else
          break;
   }
   for(i=x;i<=y;i++)
   {
       v=last[i].val;
       if(v==mid)
       {
           if(sum)
           {
               cur[l++].val=v;
               last[i].num=last[i].p=0;
               sum--;
           }
           else
           {
               cur[r++].val=v;
               last[i].num=last[i].p=1;
           }
       }
       else if(v<mid)
       {
           cur[l++].val=v;
           last[i].num=last[i].p=0;
       }
       else
       {
           cur[r++].val=v;
           last[i].num=last[i].p=1;
       }
   }
   for(i=x+1;i<=y;i++)
      last[i].num+=last[i-1].num;
   if(x==y)  return;
   int temp=t<<1;
   build(x,m,cen+1,temp);
   build(m+1,y,cen+1,temp+1);
}
int query(int x,int y,int k,int cen,int t)
{
    Tree l=tree[cen][x],r=tree[cen][y];
    int mid=a[t].mid;
    if(a[t].x==a[t].y)
        return l.val;
    int dif=(y-x+1)-(r.num-l.num+l.p);
    if(dif>=k)
        return query(x-l.num+l.p,y-r.num,k,cen+1,t*2);
    else
        return query(mid+l.num+1-l.p,mid+r.num,k-dif,cen+1,t*2+1);
}
int main()
{
    int t,n,m,i,j,k;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(i=1;i<=n;i++)
        {
            scanf("%d",&st[i]);
            tree[0][i].val=st[i];
        }
        sort(st+1,st+1+n);
        build(1,n,1,1);
        while(m--)
        {
            scanf("%d%d%d",&i,&j,&k);
            printf("%d\n",query(i,j,k,0,1));
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值