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

POJ 2104 K-th Number

时间:2015-06-18 23:31:15      阅读:116      评论:0      收藏:0      [点我收藏+]

标签:

题意:给出一个序列,若干查询,询问区间l到r的第k小值。

 

解法:划分树可以最有效的解决这个问题……但是划分树只能解决这个问题= =主席树的应用范围比较广……所以只学了主席树……嗯……

膜拜发明主席树的大神,引用一下他的话

..这个东西是当初我弱不会划分树的时候写出来替代的一个玩意..被一小撮别有用心的人取了很奇怪的名字<

想法是对原序列的每一个前缀[1..i]建立出一颗线段树维护值域上每个数的出现次数,然后发现这样的树是可以减的,然后就没有然后了

通过这位大神的博客学习了原理http://blog.csdn.net/metalseed/article/details/8045038

通过这位大神的博客学习了代码http://www.cnblogs.com/Rlemon/archive/2013/05/23/3094635.html

 

代码:

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<math.h>
#include<limits.h>
#include<time.h>
#include<stdlib.h>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#define LL long long
#define MAXN 100010

using namespace std;

struct node
{
    int sum;
    int ls, rs;
    node() {sum = 0, ls = 0, rs = 0;}
}T[MAXN * 20];
int a[MAXN], b[MAXN], p[MAXN];//a是原数组,p代表a数组下标,b是离散化后数组
int root[MAXN];//记录每个结点在T中的下标
int sz;//当前数组使用长度
void ins(int &i, int l, int r, int x)
{
    T[++sz] = T[i];//复制上一节点作为新结点
    i = sz;//更新当前结点下标
    T[i].sum++;//更新线段树维护的和
    if(l == r)
        return ;
    int m = (l + r) >> 1;
    if(x <= m) ins(T[i].ls, l, m, x);//更改左儿子
    else ins(T[i].rs, m + 1, r, x);//更改右儿子
}
int query(int i, int j, int l, int r, int k)
{
    if(l == r)
        return l;
    int t = T[T[j].ls].sum - T[T[i].ls].sum;//r线段树减去l-1的线段树值
    int m = (l + r) >> 1;
    if(t >= k) return query(T[i].ls, T[j].ls, l, m, k);
    else return query(T[i].rs, T[j].rs, m + 1, r, k - t);
}
bool cmp(int i, int j)
{
    return a[i] < a[j];
}
int main()
{
    int n, m;
    while(~scanf("%d%d", &n, &m))
    {
        for(int i = 1; i <= n; i++)
            scanf("%d", &a[i]), p[i] = i;
        sort(p + 1, p + n + 1, cmp);//按原数组大小对下标排序
        for(int i = 1; i <= n; i++)//离散化
            b[p[i]] = i;
        sz = 0;
        root[0] = 0;
        for(int i = 1; i <= n; i++)
        {
            root[i] = root[i - 1];
            ins(root[i], 1, n, b[i]);
        }
        while(m--)
        {
            int l, r, k;
            scanf("%d%d%d", &l, &r, &k);
            int t = query(root[l - 1], root[r], 1, n, k);
            printf("%d\n", a[p[t]]);
        }
    }
    return 0;
}

  

POJ 2104 K-th Number

标签:

原文地址:http://www.cnblogs.com/Apro/p/4587133.html

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