HDU_2665 Kth number[可持续化线段树]

传送门:HDU_2665

Kth number

Problem Description
Give you a sequence and ask you the kth big number of a inteval.
 

Input
The first line is the number of the test cases.
For each test case, the first line contain two integer n and m (n, m <= 100000), indicates the number of integers in the sequence and the number of the quaere.
The second line contains n integers, describe the sequence.
Each of following m lines contains three integers s, t, k.
[s, t] indicates the interval and k indicates the kth big number in interval [s, t]
 

Output
For each test case, output m lines. Each line contains the kth big number.
 

Sample Input
  
  
1 10 1 1 4 2 3 5 6 7 8 9 0 1 3 2
 

Sample Output
  
  
2

题意:求区间第K大树。

思路:可持续化线段树。


代码:

/************************************************
* Author: Ac_sorry
* File:
* Create Date:
* Motto: One heart One life
* CSDN: http://blog.csdn.net/code_or_code
*************************************************/

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<vector>
#include<string>
#include<map>
#include<utility>
#include<queue>
#include<stack>
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define seed_ 131
#define eps 1e-8
#define mem(a,b) memset(a,b,sizeof a)
#define w(p) tree[p].w
#define ls(p) tree[p].ls
#define rs(p) tree[p].rs
using namespace std;
typedef long long LL;

const int N=100010;
int a[N],b[N];
int root[N],sz;

struct node{
    int ls,rs;
    int w;
    node(){ls=rs=w=0;}
}tree[N*20];

void update(int &i,int l,int r,int x)
{
    tree[++sz]=tree[i];i=sz;
    w(i)++;
    if(l==r) return;
    int m=(l+r)>>1;
    if(x<=m) update(ls(i),l,m,x);
    else update(rs(i),m+1,r,x);
}

int query(int i,int j,int l,int r,int k)
{
    if(l==r) return l;
    int t=w(ls(j))-w(ls(i));
    int m=(l+r)>>1;
    if(t>=k) return query(ls(i),ls(j),l,m,k);
    else return query(rs(i),rs(j),m+1,r,k-t);
}


int main()
{
    int T_;scanf("%d",&T_);
    //int AC=0;
    while(T_--)
    {
        root[0]=0;
        sz=0;
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",a+i);
            b[i]=a[i];
        }
        sort(b+1,b+1+n);
        int cnt=unique(b+1,b+1+n)-(b+1);
        int mpp;
        for(int i=1;i<=n;i++)
        {
            root[i]=root[i-1];
            mpp=lower_bound(b+1,b+1+cnt,a[i])-b;
            update(root[i],1,cnt,mpp);
        }
        int l,r,k;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&l,&r,&k);
            int pos=query(root[l-1],root[r],1,cnt,k);
            printf("%d\n",b[pos]);
        }

    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值