Live2d Test Env

HDU2665Kth number (主席树+离散)

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

InputThe 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]OutputFor 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小,可能写错了还是怎么的。
  •  
  •    个人觉得既学习了主席树,也同时对离散的认识也加强了吧,表示以前没有用过unique结合lower_bound来离散操作。
  •  
  •    没有格外的插入操作,不需要init和memset。但是要记住加地址符。
  •  
  •    从现在开始,代码格式要更加规范,比如符号两边加空格。
  •    Persistent line tree ,我姑且函数起名PIT,如果知道了其英文名字再改过来。
  •    每次查询时范围都是(1,sz);和普通的线段树的区别是:普通线段树从root=1开始沿下走。而主席树是沿两个root向下走,走的方向是一样的。
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=100010;
int a[maxn],b[maxn],T,n,sz,q,cnt,ql,qr,x;
int ch[maxn * 20][2],sum[maxn * 20],rt[maxn * 20];
struct PLTree
{
    
    void build(int& now,int l,int r)
    {
        now = ++ cnt;
        sum[now] = 0;//ch[now][0],cnt[now][1]没必要跟新,后面sum会跟新。 
        if(l == r) return ;
        int Mid = (l + r)>>1;
        build(ch[now][0],l,Mid);
        build(ch[now][1],Mid + 1,r);
    }
    void insert(int& now,int last,int l,int r,int pos)
    {
        now = ++ cnt;
        ch[now][0]=ch[last][0];//假设公共,不同的部分下面再跟新。 
        ch[now][1]=ch[last][1];
        sum[now] = sum[last] + 1;
        if(l == r) return ; 
        int Mid = (l+r) >> 1;
        if(pos <= Mid) insert(ch[now][0],ch[last][0],l,Mid,pos);
        else insert(ch[now][1],ch[last][1],Mid + 1,r,pos);
    }
    int query(int ss,int tt,int l,int r,int k)
    {
         if(l == r) return l;//要位置 ,不是要值
         int Mid =(l + r) >> 1,tmp = sum[ch[tt][0]] - sum[ch[ss][0]];//本身呢? 
         if(k <= tmp) return query(ch[ss][0],ch[tt][0],l,Mid,k);
         else return query(ch[ss][1],ch[tt][1],Mid + 1,r,k - tmp);
    }
    void work()
    {
        scanf("%d%d%d",&ql,&qr,&x);
        int ans = query(rt[ql - 1],rt[qr],1,sz,x);//注意这个范围是(1,sz),和建树的时候的长度一样。
        printf("%d\n",b[ans]);
    }
};
PLTree P;
int main(){
    scanf("%d",&T);
    while(T--){
        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);
        sz = unique(b + 1,b + n + 1)-(b + 1);
        cnt=0;
        P.build(rt[0],1,sz);
        for(int i = 1;i <= n;i ++) a[i]=lower_bound(b + 1,b + sz + 1,a[i]) - b;//a现在是排名 
        for(int i = 1;i <= n;i ++) P.insert(rt[i],rt[i-1],1,sz,a[i]); 
        while(q--)  P.work();
    }
    return 0;
}

 

posted @ 2017-11-30 21:02  nimphy  阅读(345)  评论(0编辑  收藏  举报