码迷,mamicode.com
首页 > 其他好文 > 详细

求动区间第k小(离线,线段树)

时间:2015-06-04 06:10:42      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:

#include<bits/stdc++.h>
const int M = 1e5 + 10 ;
int n , m ;
int ql , qr , k ;
int a[M] , sum [M] , p[M] ;
int id = 0 ;

void build (int o , int l , int r)
{
    if (l == r) {
        sum[o] = 1 ;
        return ;
    }
    int mid = (l + r) >> 1 ;
    build (o << 1 , l , mid) ;
    build (o << 1 | 1 , mid + 1 , r ) ;
    sum[o] = sum[o << 1] + sum[o << 1 | 1] ;
}

void query (int o , int l , int r )
{
    if (id != -1) return ;
    if (l >= ql && r <= qr) {
        if (k > sum[o]) {
            k -= sum[o] ; return ;
        }
        if (l == r ) {  
            id = l ; return ;
        }
    }
    int mid = (l + r) >> 1 ;
    if (ql <= mid) query (o << 1 , l , mid ) ;
    if (qr > mid ) query (o << 1 | 1 , mid + 1 , r) ;
}

int main ()
{
    freopen ("a.txt" , "r" , stdin ) ;
    scanf ("%d%d" , &n , &m) ;
    for (int i = 1 ; i <= n ; i ++) {
        scanf ("%d" , &a[i]) ;
        p[i] = i ;
    }
    build (1 , 1 , n ) ;
    std::sort (p + 1 , p + 1 + n , [](int i , int j) {return a[i] <= a[j] ;}) ;
    while (m --) {
        id = -1 ;
        scanf ("%d%d%d" , &ql , &qr , &k) ;
        query (1 , 1 , n ) ;
        printf ("%d\n" , a[ p[id] ]) ;
    }
    return 0 ;
}

写这个真是要了点Hp,不知道为什么大神都喜欢用函数式线段树来搞,然而并不需要吧。在岐哥,杰哥的理论指导下,还有进爷的技术性指导下,92版完成了,orz。

需要注意的是这是离线的做法,所以一开始我们要把总的个数(算上后来会添加的)算在n内。(接着离散化)

求动区间第k小(离线,线段树)

标签:

原文地址:http://www.cnblogs.com/get-an-AC-everyday/p/4550763.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!